我正在阅读一个包含 unsigned char
变量的 .cpp 文件,它正在尝试进行 16 位的按位左移操作。由于一个 unsigned char
由 8 个 bit 组成,左移 16 位将擦除所有 bit 并用八个0填充。
unsigned char byte=0xff; byte << 16;
我正在阅读一个包含 unsigned char
变量的 .cpp 文件,它正在尝试进行 16 位的按位左移操作。由于一个 unsigned char
由 8 个 bit 组成,左移 16 位将擦除所有 bit 并用八个0填充。
unsigned char byte=0xff; byte << 16;
当你进行值的移位时,
unsigned char x = ...;
int y = x << 16;
如果unsigned char
适合于int
(大多数系统),则将x
的类型提升为int
,否则提升为unsigned
(罕见情况1)。只要你的int
宽度至少为25位,那么就不会丢失任何数据2。
请注意,这与数字16
的类型为int
完全无关。
/* All three are exactly equivalent */
x << 16;
x << 16u;
x << (unsigned char) 16;
来源:来自n1516(C99草案)
§6.5.7第3段:位移操作符
对每个操作数执行整数提升。结果的类型是提升后的左操作数的类型。
§6.3.1.1第2段:布尔值、字符和整数
如果int可以表示原始类型的所有值(由位域限制),则该值转换为int;否则,它将被转换为无符号int。这些被称为整数提升。
脚注:
1:一些DSP芯片以及某些Cray超级计算机众所周知sizeof(char) == sizeof(int)
。 这简化了处理器的加载存储单元的设计,但增加了内存消耗。
2:如果左移通过提升到int
然后溢出int
,那么这是未定义行为(恶魔可能从你的鼻子里飞出来)。相比之下,溢出unsigned
总是有明确定义的,因此位移应该通常在unsigned
类型上进行。
unsigned char
提升为int
后可能会意外覆盖的内存感到困惑。 - leomayleomayint
赋值给一个unsigned char
变量,那么int
会被转换。(毕竟这不是汇编语言。) - Dietrich Eppx = x << 16
,那么在大多数系统上,这等同于 x = 0
。 - Dietrich Eppchar
适合于int
,它将被提升为int
,结果将如您所期望的那样。如果不是这种情况,则根据标准,它是未定义的行为,并且可能会发出编译警告。从标准来看:
对每个操作数执行整数提升。结果的类型是提升后左操作数的类型。如果右操作数的值为负或大于或等于提升后左操作数的宽度,则行为是未定义的。
char
无法适应于 int
,那么它必须适应于 unsigned int
,因此不会导致未定义的行为。只有有符号整数的移位是未定义的,而且仅当数学结果不能由该类型表示时才是未定义的。例如,如果 int
是16位,则 1 << 16
是未定义的。 - Dietrich Eppunsigned char
被提升为 int
而不是 unsigned int
且移位操作将产生一个无法表示为 int
的值时,行为才是未定义的。 - cafint
是16位,0 << 16
也是未定义的行为,因为这个答案中指出的约束条件。 - caf