在我的编译器上,以下伪代码(用二进制替换的值):
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 / 2 E2商的整数部分。如果E1
具有带符号类型和负值,则结果值是实现定义的,并且可以是算术(有符号)移位:
或逻辑(无符号)移位:
此不兼容的代码示例无法测试右操作数是否大于或等于提升的左操作数的宽度,允许未定义的行为。
unsigned int ui1;
unsigned int ui2;
unsigned int uresult;
/* Initialize ui1 and ui2 */
uresult = ui1 >> ui2;
假设右移是作为算术(有符号)移位还是逻辑(无符号)移位实现的,也可能导致漏洞。见建议INT13-C。仅对无符号操作数使用位运算符。
来自最新的 C++20 草案:
有符号整数类型的右移是算术右移,它执行符号扩展。
不,你不能依赖这种行为。负量的右移(我假设您的示例正在处理)是实现定义的。
在 C++ 中,没有。它取决于实现和/或平台。
在其他一些语言中,是的。例如,在 Java 中,>> 运算符被精确定义为始终使用最左边的位进行填充(从而保留符号)。>>> 运算符使用 0 填充。因此,如果您想要可靠的行为,一个可能的选择是更改为另一种语言。(虽然很明显,根据您的情况,这可能不是一个选择。)
AFAIK 整数可以在 c++ 中表示为符号大小,在这种情况下,符号扩展将填充 0。所以你不能依赖这个。