存储“字节数组”(blob ...)时,使用char
或存储unsigned char
项目(unsigned char
又名uint8_t
)更好吗?(标准说sizeof
两者都是 1 字节。)
这有关系吗?还是一种比另一种更方便或更流行?也许,像 Boost 这样的库使用什么?
如果char
是有符号的,那么对设置了高位的字节值执行算术运算将导致在提升为时进行符号扩展int
;所以,例如:
char c = '\xf0';
int res = (c << 24) | (c << 16) | (c << 8) | c;
将给出0xfffffff0
而不是0xf0f0f0f0
. 这可以通过用 屏蔽来避免0xff
。
char
如果您正在与使用它而不是unsigned char
.
请注意,从char *
to/from 转换unsigned char *
始终是安全的 (3.9p2)。支持的一个哲学理由unsigned char
是标准中的 3.9p4 支持它,至少在表示可以保存对象的内存表示的字节数组时:
类型对象的对象表示是类型对象占用的对象
T
序列,其中等于。N
unsigned char
T
N
sizeof(T)
理论上,C++ 中字节的大小取决于编译器设置和目标平台,但保证至少为 8 位,这就解释了为什么sizeof(uint8_t)
要求为 1。
以下是标准对它的更准确说法
§1.71
C++ 内存模型中的基本存储单元是字节。一个字节至少大到足以包含基本执行字符集 (2.3) 的任何成员和 Unicode UTF-8 编码形式的八位代码单元,并且由连续的位序列组成,其数量为实现定义。最低有效位称为低位;最高有效位称为高位。C++ 程序可用的内存由一个或多个连续字节序列组成。每个字节都有一个唯一的地址。
因此,如果您正在处理一些字节不是 8 位的特殊硬件,它可能会产生实际的影响。否则,我会说这是一个品味问题,以及您想通过选择类型来传达什么信息。
可能对 blob 使用有符号值的其他问题之一是该值将取决于符号表示,这不是标准的一部分。因此,调用未定义的行为更容易。
例如...
signed char x = 0x80;
int y = 0xffff00ff;
y |= (x << 8); // UB
实际的算术值也将严格取决于二进制补码,这可能会给一些人带来惊喜。显式使用 unsigned 可以避免这些问题。
尽管从可读性的角度来看,如果类型unsigned char
暗示值 0..255 可能会更清楚,但实际上并没有什么区别。