【问题标题】:Type "char" in C++在 C++ 中键入“字符”
【发布时间】:2013-12-06 00:48:07
【问题描述】:

如果您不知道运行代码的机器的默认设置,是否有一种简单的方法可以在 charunsigned char 之间进行转换? (在大多数架构上,char 默认是有符号的,因此范围从 -128+127。在其他一些架构上,例如 ARM,char 默认是无符号的,范围从 0 到 255 ) 我正在寻找一种方法来选择正确的符号或透明地在两者之间进行转换,最好是不涉及太多步骤的方法,因为我需要对数组中的所有元素执行此操作。

使用预处理器定义将允许在我的代码开头进行设置。
就像指定 char 的显式形式一样,例如 signed charunsigned char,因为只有 char 在平台之间是可变的。

原因是,我想使用一些库函数(例如 strtol),它们接受 char as an argument 但不接受 unsigned char

我正在寻找一些建议或一些正确方向的指示,以了解什么是一种实用有效的方法来使代码可移植,因为我打算在几台具有不同默认设置的机器上运行代码对于char

【问题讨论】:

  • 请为每个问题发布一个问题,我认为以目前的形式无法回答这个问题。
  • 欢迎来到 StackOverflow!请注意,关于 StackOverflow 的问题必须由具体参考而非意见来回答 - 因此,应避免“我应该做 X”或“什么是 Y 的好资源”的问题。另请注意,一个问题应涵盖一个具体问题。
  • c++中char有3种类型(charunsigned charsigned char),所以这实际上是一个很好的可移植性问题。 @reila-lee 开始与我聊天,我将发布一个答案,尽我所能涵盖您的所有问题:)
  • sourceforge.net/p/predef/wiki/Architectures 处有一个预定义宏列表,这可能会有所帮助,这样您就可以检测它在哪个架构上运行,并由此确定 char 的默认设置。
  • 在二进制补码机上,它只是一个解释问题。因此,对于 7 位字符集,完全没有区别。

标签: c++ char portability unsigned-char


【解决方案1】:

在这一点上我觉得没有任何实际问题。

默认情况下签名或未签名的架构不是问题。这是编译器的问题,可以根据需要在两个选项之间更改默认设置。

此外,无需在类型之间进行转换。两者在内存中的表示形式相同,位数相同(通常为 8)。这只是您的程序及其用于解释位的库的问题。如果你要调用strtol,那么你的数据是一个字符数组,你应该使用普通的char

如果您曾经使用char 存储的不是字符(Abf ...)而是实际值(-1、0、42 ...),那么范围很重要.在这种情况下,您必须使用signed charunsigned char。但是在这种情况下,需要char * 的库函数几乎没有用处。

对于这些确实需要带有实际二进制 blob 的 char * 的库,没有问题。使用您喜欢的类型(有符号、无符号或未确定)创建二进制缓冲区,然后发送它,可能带有强制转换。它会完美运行。

【讨论】:

  • 完全正确。唯一可能发生的问题是,如果您将 unsigned char * 转换为 signed char * 或反之亦然,并且值小于 0/大于 127,并且在不使用 2 的补码表示的系统上。但你不应该遇到这种情况。如果您将字符串传递给像 strtol 这样的库函数,那么首先您不应该有任何超出 ASCII 范围的字符!
  • 我正在使用“unsigned char”来存储字节大小的值并使用它们执行模运算。截至目前,我的程序接受用户输入的类型为“char”数组的有效十六进制字符串(例如,AC24F5)。然后,我使用“strtol”一次读取字符串 2 个字符作为字节的十六进制表示,并将结果值存储为“unsigned char”类型。我想标准化“char”的使用的一个原因是因为我可以直接将一个“unsigned char”数组输入到一半大小的程序中,并绕过读取和重新存储的过程。
【解决方案2】:

C++ 有三种char 类型,但只有char 允许在编译器/体系结构之间变化,因为其他两个是显式版本,char 是隐式的,因此允许默认为signedunsigned.

要使您的代码可移植,最直接的做法是根据需要显式使用signedunsigned char,但是为了便于阅读,您可能更愿意将char 重新定义为您需要的类型,或者甚至可以自己定义char(出于演示目的,我将使用RLChar

第一个版本 - 取消定义字符并重新定义

#ifdef __arm__
#undef char
#define char signed char
#endif

第二版 - 定义您自己的自定义字符类型以在您的代码中使用

#ifndef RLChar
#define RLChar signed char
#endif

(我个人倾向于第二个)

您还可以创建另一个宏以允许在两者之间进行更改:

#define CLAMP_VALUE_TO_255(v) ((v) > 255 ? 255 : ((v) < 0 ? 0 : (v)))

那么你可以使用:

unsigned char clampedChar = CLAMP_VALUE_TO_255((unsigned char)pixel)

或使用强制转换,例如(如果您将使用的所有编译器都支持它,这些就是要走的路):

signed char myChar = -100;
unsigned char mySecondChar;
mySecondChar = static_cast<unsigned char>(myChar); // uses a static cast 
mySecondChar = reinterpret_cast<unsigned char&>(myChar); // uses a reinterpretation cast

所以对于您的阵列场景,您可以这样做

unsigned char* RLArray;
RLArray = reinterpret_cast<unsigned char*>(originalSignedCharArray); 

如果您需要更多信息,请告诉我,因为这正是我能记住的,特别是如果您需要 C 等价物或更多详细信息。 :)

【讨论】:

  • 我一直将类型“byte”定义为“unsigned char”。我想知道将“char”重新定义为“unsigned char”是否会在以后给我带来麻烦,例如在库函数中?我只是在使用“iostream”、“cmath”和“cstdlib”等标准库。
  • none at all:) 实际上,char 只是您选择/编译器制造商选择的 signedunsigned char 中的任何一个的别名。这就是它可能因平台而异的原因:)
猜你喜欢
  • 1970-01-01
  • 2011-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-20
相关资源
最近更新 更多