题
字节缓冲区应该是有符号字符还是无符号字符,还是只是一个字符缓冲区?C 和 C++ 之间有什么区别吗?
谢谢。
解决方案
字节的缓冲区是否应该签名或无符号char或仅仅是炭缓冲区?C和C ++有什么区别吗?
语言对待它的方式略有不同。A 巨大的 惯例对待它的方式有所不同。
char
= ASCII(或UTF-8,但符号会妨碍) 文本的 数据unsigned char
= 字节signed char
= 很少使用
并且有代码 依赖 就这样的区别。就在一两周前,我遇到了一个错误,JPEG 数据被损坏,因为它被传递到 char*
我们的 Base64 编码函数的版本——它“有效地”替换了“字符串”中所有无效的 UTF-8。更改为 BYTE
又名 unsigned char
只需要修复它即可。
其他提示
如果您打算存储任意的二进制数据,你应该使用unsigned char
。这是保证具有由C标准没有填充比特的唯一数据类型。相互数据类型可能包含填充比特在其对象表示(即,而不是只有那些确定的值,其中包含一个对象的所有位的一个)。填充比特状态是不确定的,并且不被用于存储值。所以,如果你阅读使用char
一些二进制数据,事情会被削减为char的取值范围(通过解释只值位),但也有可能仍然是刚刚忽略位,但仍然在那里,由memcpy
阅读。就像在真实的结构对象填充位。类型unsigned char
是保证不包含这些。从5.2.4.2.1/2
下面(C99 TC2,这里n1124):
如果在使用时char类型的对象的值被视为有符号整数 表达,
CHAR_MIN
的值应是相同的SCHAR_MIN
和CHAR_MAX
的值应是相同SCHAR_MAX
的。否则,值CHAR_MIN
应在0和CHAR_MAX
的值应是相同的UCHAR_MAX
。 值UCHAR_MAX
应等于2^CHAR_BIT − 1
从最后一句它遵循没有剩余任何填充比特的空间。如果您使用char
作为缓冲区的类型,你也有溢出的问题:明确指定的任何值,这是8
位范围内的一个这样的元素 - 所以你可能会想到这样的分配是好的 - 但不是内范围内的char
的,这是CHAR_MIN
..CHAR_MAX
,这种转换溢出并导致实现定义的结果,包括的信号加注。
即使上述有关的任何问题,可能不会在实际实施中显示(将是一个的非常的实施质量差),你是最好的,从使用权类型起开始,这是unsigned char
。
有关的字符串,但是,所选择的数据类型是char
,这将通过串和打印功能来理解。使用signed char
用于这些目的看起来像一个错误的决定对我来说。
有关的进一步信息,请参阅 this proposal
其中包含了C标准的下一个版本,最终将需要signed char
没有任何填充比特或者修复。它已经纳入工作文件。
这取决于
如果缓冲区是为了容纳文本,那么它很可能是有道理的声明它作为char
数组,让平台决定是否经过签名或默认无符号的。这会给你传递数据进出实施的运行时库,例如最少的麻烦。
如果缓冲区是为了保持二进制数据,那么它取决于你打算如何使用它。例如,如果二进制数据是真正的数据样本的填充阵列被符号的8位定点ADC测量,然后signed char
将是最好的。
在大多数现实世界的情况下,缓冲区就是这样,一个缓冲区,你真的不关心类型的单个字节,因为你在一个批量操作被填充的缓冲器,而你将要传递开了一个解析器来解释复杂的数据结构,并做一些有用的东西。在这种情况下,在最简单的方式声明它。
如果它实际上是8个字节的缓冲器,而不是在机器的默认语言环境的字符串,那么我会使用uint8_t
。不存在围绕其中一个char不是一个字节(或字节一个八位位组),但使得该语句“这是个八位字节的缓冲器”而不是“这是一个字符串”通常有用的文档许多机器
您应该使用的字符的或无符号字符的,但从来没有的符号字符的。该标准已在以下3.9 / 2
有关的任何对象(除了其他 基类的子对象)POD类型T的, 对象是否保持一个 类型T的有效值,底层 字节(1.7)构成可以将对象 被复制到字符数组或 无符号char.If的内容 char或unsigned char的阵列是 复制回所述对象,所述 对象应随后举行 原来的值。
这是更好地将其定义为无符号字符。逸岸的Win32类型字节定义为无符号字符。有C&此之间C ++之间没有差别。
有关最大可移植性始终使用无符号字符。有一对夫妇在那里,这可能发挥作用的实例。跨越不同类型的端系统共享串行数据立刻浮现在脑海。当执行移位或比特掩蔽值是另一回事。
的中int8_t VS uint8_t选择是类似于当您比较一个PTR为NULL到。
从一个功能点,比较NULL相同比较为0,因为NULL为0的#define。
不过个人,从一种编码风格来看,我选择我的指针,因为空的#define张三的人坚持认为你检查一个错误的指针...
代码比较NULLVS
,当有人看到比较以0它意味着您正在检查的特定值。
有关的上述原因,我会用uint8_t。
如果您取一个元素到一个较宽的变量,它当然将符号扩展或没有。结果
应该也应该......我倾向于希望的签名,因为感觉比较“原始”,少邀请说“嘿,这只是一群小ints
的”,如果我想强调数据的二进制岬。
我不认为我曾经使用过一个明确的signed char
表示字节的缓冲区。
当然,三分之一选择是表示缓冲器作为void *
尽可能。许多常见的I / O功能与void *
工作,所以有时什么整型使用的决定可以完全封装,这是很好的。
几年前,我曾与该印刷有色字符以上128 ASCII值和这是由从炭为unsigned char切换解决的C ++控制台应用程序的一个问题,但我认为它已经solveable同时保持字符类型,太。
有关现在,大多数C / C ++函数使用炭和我明白两种语言好多了,所以我在大多数情况下使用炭。
你真的关心吗?如果不这样做,就用默认值(炭),不要用无关紧要的问题搞乱你的代码。否则,将来的维护人员会在想为什么要使用有符号(或无符号)。使他们的生活变得更加简单。
如果你骗编译器,它会惩罚你。
如果缓冲区包含的数据只是路过,你将不会以任何方式操纵它们,也不要紧。
不过,如果你对缓冲区的内容进行操作,那么正确的类型声明将会使你的代码更简单。否为 “int VAL = BUF [I]&0xff的;”无义。
所以,想想什么是真正的数据是,你需要如何使用它。
typedef char byte;
现在你可以让你的阵列是byte
s的。这是有目共睹的你的意思,你不会失去任何功能。
我知道这是愚蠢的有点,但它使你的代码读取100%,你打算。