在我的编译器上,以下伪代码(值替换为二进制):
sint32 word = (10000000 00000000 00000000 00000000);
word >>= 16;
生成一个带有比特域的 word
:
(11111111 11111111 10000000 00000000)
我可以在所有平台和C++编译器上依赖这种行为吗?
在我的编译器上,以下伪代码(值替换为二进制):
sint32 word = (10000000 00000000 00000000 00000000);
word >>= 16;
生成一个带有比特域的 word
:
(11111111 11111111 10000000 00000000)
我可以在所有平台和C++编译器上依赖这种行为吗?
以下是链接:INT34-C. 不要使用负数位数或大于等于操作数中存在的位数来移位表达式
不合规的代码示例(右移)
E1 >> E2
的结果是 E1
右移 E2
位。如果 E1
具有无符号类型或者 E1
具有带符号类型和非负值,则结果的值为 E1 / 2E2 的整数部分。如果 E1
具有带符号类型和负值,则得到的值是实现定义的,可能是算术(带符号)移位:
或逻辑(无符号)移位:
这个不合规的代码示例没有测试右操作数是否大于或等于推广的左操作数的宽度,因此导致未定义的行为。
unsigned int ui1;
unsigned int ui2;
unsigned int uresult;
/* Initialize ui1 and ui2 */
uresult = ui1 >> ui2;
假设一个右移运算是以算术(有符号)还是逻辑(无符号)方式实现的,可能会导致漏洞。请参见建议INT13-C. 仅对无符号操作数使用位运算符。
来自最新的C++20草案:
有符号整数类型的右移是算术右移,它执行符号扩展。
不可以依赖此行为。右移负数(我猜测您的示例处理的就是这种情况)是有实现定义的。
在C++中,不是的。这取决于实现和/或平台。
在其他一些语言中,是的。例如,在Java中,“>>”运算符被定义为始终使用最左侧的位进行填充(从而保留符号)。“>>>”运算符使用0进行填充。因此,如果您想要可靠的行为,则可能的一个选项是更改为另一种语言。(尽管显然,根据您的情况,这可能不是一个选项。)