字节缓冲区应该是有符号字符还是无符号字符,还是只是一个字符缓冲区?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_MAXUCHAR_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张三的人坚持认为你检查一个错误的指针...

代码比较NULL

VS

,当有人看到比较以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;

现在你可以让你的阵列是bytes的。这是有目共睹的你的意思,你不会失去任何功能。

我知道这是愚蠢的有点,但它使你的代码读取100%,你打算。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top