C++ 将无符号字符按位左移16是什么意思

C++ 将无符号字符按位左移16是什么意思,c++,c,bit-manipulation,C++,C,Bit Manipulation,我正在读取一个包含无符号字符变量的.cpp文件,它正在尝试按位左移16位,因为无符号字符由8位组成,左移16位将擦除所有位并用8个0填充 无符号字符字节=0xff;字节如果char适合int,它将被提升为int,结果将与您期望的一样。如果不是这样,根据标准,它是未定义的行为,并且可能会发出编译警告。根据标准: 对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。如果右操作数的值为负数或大于或等于提升后的左操作数的宽度,则行为未定义。当您移动值时 unsigned char x = ...

我正在读取一个包含
无符号字符
变量的.cpp文件,它正在尝试按位左移16位,因为
无符号字符
由8位组成,左移16位将擦除所有位并用8个0填充


无符号字符字节=0xff;字节如果
char
适合
int
,它将被提升为
int
,结果将与您期望的一样。如果不是这样,根据标准,它是未定义的行为,并且可能会发出编译警告。根据标准:


对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。如果右操作数的值为负数或大于或等于提升后的左操作数的宽度,则行为未定义。

当您移动值时

unsigned char x = ...;
int y = x << 16;
来源:来自n1516(C99草稿):

§6.5.7第3段:位移位运算符

对每个操作数执行整数提升。结果的类型是 提升后的左操作数的值

§6.3.1.1第2段:布尔值、字符和整数

如果int可以表示原始类型的所有值(受宽度限制,例如 位字段),将值转换为整数;否则,它将转换为未签名的 整数。这些被称为整数促销

脚注:

1:一些DSP芯片以及某些克雷超级计算机已知具有
sizeof(char)==sizeof(int)
。这以额外的内存消耗为代价简化了处理器负载存储单元的设计


2:如果你的左移位被提升到
int
,然后溢出
int
,这是未定义的行为(恶魔可能会从你鼻子里飞出来)。相比之下,溢出一个
无符号
总是定义良好的,因此位移位通常应该在
无符号
类型上进行。

表达式的值没有赋值。如前所述,编译器将优化移位操作,而不执行任何操作。真正的代码是什么?您可能想看看这个:所有内置操作符都处理至少为int大小的对象(请参阅)。因此:
sizeof(字节如果
char
不能放入
int
,它将永远不会导致未定义的行为,因为它必须装入
无符号int
,并且
无符号int
上的移位永远不会被定义。只有有符号整数上的移位才是未定义的,并且只有当数学结果不能用类型表示时。例如le,
1整数提升确实被执行,这意味着只有当
无符号字符
被提升为
int
而不是
无符号int
时,行为才是未定义的,并且移位将产生一个无法在
int
@DietrichEpp中表示的值:甚至
0非常感谢您的精心设计解释。虽然我仍然对将
unsigned char
升级为
int
@leomayleomay后可能意外覆盖的内存感到困惑。但它不是这样工作的。如果将
int
赋值给
unsigned char
变量,则会转换
int
。(这毕竟不是汇编语言。)所以这里的按位左移(16向左)将使所讨论的变量为0,对吗?如果赋值
x=x,我发现这种行为非常令人惊讶。我使用IAR CSTAT静态分析工具为以下代码遇到了这种行为:无符号短BE2LE16(无符号短x){return((x8));}直到你详细的回答才明白。非常感谢你和我!
/* All three are exactly equivalent */
x << 16;
x << 16u;
x << (unsigned char) 16;