Char与unsigned char在字节数组中的区别

13
在存储"字节数组"(二进制大对象...)时,使用char还是unsigned char(也称为uint8_t)更好?(标准规定两者的sizeof都恰好为1个字节。)
这是否重要?或者其中一个比另一个更方便或普遍?也许像Boost这样的库使用哪种类型?

2
@nightcracker 或许你能指出重复的部分? - Cartesius00
重复问题,参见 https://dev59.com/xHRB5IYBdhLWcg3wWF8H。 - kebs
4个回答

14

如果char是有符号的,那么在将带有高位设置的字节值提升为int时进行算术运算将导致符号扩展; 因此,例如:

char c = '\xf0';
int res = (c << 24) | (c << 16) | (c << 8) | c;

将会返回0xfffffff0而不是0xf0f0f0f0。可以通过使用掩码0xff来避免这种情况。

如果你需要与使用char的库进行接口交互,那么char仍然可能更可取。

请注意,从char *unsigned char *的转换始终是安全的(3.9p2)。支持unsigned char的一个哲学原因是标准中的3.9p4,至少对于表示可能包含对象内存表示的字节数组而言:

类型为T的对象的对象表示是由类型为T的对象占用的Nunsigned char对象序列,其中N等于sizeof(T)


2
理论上,C++中的字节大小取决于编译器设置和目标平台,但保证至少为8位,这就解释了为什么需要sizeof(uint8_t)为1。
以下是标准对此的更精确说明:
§1.71
基本存储单位在C++内存模型中是字节。一个字节至少要足够容纳基本执行字符集(2.3)中的任何成员以及Unicode UTF-8编码形式的八位代码单元,并由一系列连续的位组成,其中位数是实现定义的。最低有效位称为低位,最高有效位称为高位。C++程序可用的内存由一个或多个连续字节序列组成。每个字节都有一个唯一的地址。
因此,如果您正在使用某些特殊硬件,其中字节不是8位,则可能会产生实际差异。否则,我认为这只是品味问题,取决于您想通过类型选择传达什么信息。

1

另一个可能使用有符号值来处理 blob 的问题是它的值将取决于符号表示,而这并不是标准的一部分。因此,会更容易引起未定义行为。

例如...

signed char x = 0x80;
int y = 0xffff00ff;

y |= (x << 8); // UB

实际算术值也严格依赖于二进制补码,这可能会让一些人感到惊讶。使用无符号数可以避免这些问题。

0

从实际效果来看并没有什么区别,但从可读性的角度来看,如果类型是unsigned char,则意味着值为0..255,这可能更加清晰。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接