Ann*_*inn 17 c++ bit-shift platform-specific
在我的编译器上,以下伪代码(用二进制替换的值):
sint32 word = (10000000 00000000 00000000 00000000);
word >>= 16;
Run Code Online (Sandbox Code Playgroud)
生成一个如下所示word的位域:
(11111111 11111111 10000000 00000000)
Run Code Online (Sandbox Code Playgroud)
我的问题是,我可以依赖所有平台和C++编译器的这种行为吗?
And*_*ark 23
从以下链接:
INT34-C.不要将表达式移位负数位或大于或等于操作数中存在的位数
不合规代码示例(右移)
结果E1 >> E2是E1右移位E2位置.如果E1具有无符号类型或者E1具有有符号类型和非负值,则结果的值是E1/2 E2的商的整数部分.如果E1具有有符号类型和负值,则结果值是实现定义的,可以是算术(签名)移位:

或逻辑(无符号)转变:

这个不合规的代码示例无法测试右操作数是否大于或等于提升的左操作数的宽度,从而允许未定义的行为.
unsigned int ui1;
unsigned int ui2;
unsigned int uresult;
/* Initialize ui1 and ui2 */
uresult = ui1 >> ui2;
Run Code Online (Sandbox Code Playgroud)
假设右移是实现为算术(带符号)移位还是逻辑(无符号)移位也可能导致漏洞.见建议INT13-C.仅在无符号操作数上使用按位运算符.
小智 16
来自最新的 C++20 草案:
有符号整数类型的右移是算术右移,它执行符号扩展。
R. *_*des 13
不,你不能依赖这种行为.负数量的右移(我假设你的例子正在处理)是实现定义的.
在C++中,没有.它取决于实现和/或平台.
在其他一些语言中,是的.例如,在Java中,>>运算符被精确定义为始终使用最左边的位填充(从而保留符号).>>>运算符使用0填充.因此,如果您需要可靠的行为,一种可能的选择是更改为其他语言.(虽然很明显,根据您的具体情况,这可能不是一种选择.)