右移和有符号整数
在我的编译器上,以下伪代码(值替换为二进制):
sint32 word = (10000000 00000000 00000000 00000000);
word >>= 16;
生成一个 word
,其位字段如下所示:
(11111111 11111111 10000000 00000000)
我可以在所有平台和 C++ 编译器上依赖此行为吗?
On my compiler, the following pseudo code (values replaced with binary):
sint32 word = (10000000 00000000 00000000 00000000);
word >>= 16;
produces a word
with a bitfield that looks like this:
(11111111 11111111 10000000 00000000)
Can I rely on this behaviour for all platforms and C++ compilers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
从以下链接:
INT34-C。请勿将表达式移位负数位数或大于或等于操作数中存在的位数
不合规代码示例(右移)
E1>> E2
是E1
右移的E2
位位置。如果E1
为无符号类型,或者E1
为有符号类型且非负值,则结果值为 E1 / 2 商的整数部分E2。如果E1
具有有符号类型和负值,则结果值由实现定义,并且可以是算术(有符号)移位:或逻辑(无符号)移位:
此不符合规定代码示例无法测试右操作数是否大于或等于提升的左操作数的宽度,从而允许未定义的行为。
假设右移是作为算术(有符号)移位还是逻辑(无符号)移位来实现,也可能导致漏洞。请参阅建议 INT13-C。仅对无符号操作数使用按位运算符。
From the following link:
INT34-C. Do not shift an expression by a negative number of bits or by greater than or equal to the number of bits that exist in the operand
Noncompliant Code Example (Right Shift)
The result of
E1 >> E2
isE1
right-shiftedE2
bit positions. IfE1
has an unsigned type or ifE1
has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. IfE1
has a signed type and a negative value, the resulting value is implementation defined and can be either an arithmetic (signed) shift:Or a logical (unsigned) shift:
This noncompliant code example fails to test whether the right operand is greater than or equal to the width of the promoted left operand, allowing undefined behavior.
Making assumptions about whether a right shift is implemented as an arithmetic (signed) shift or a logical (unsigned) shift can also lead to vulnerabilities. See recommendation INT13-C. Use bitwise operators only on unsigned operands.
来自 最新的 C++20 草案:
有符号整数类型的右移是算术右移,执行符号扩展。
From the latest C++20 draft:
Right-shift on signed integral types is an arithmetic right shift, which performs sign-extension.
不,你不能依赖这种行为。负数的右移(我假设您的示例正在处理)是实现定义的。
No, you can't rely on this behaviour. Right shifting of negative quantities (which I assume your example is dealing with) is implementation defined.
在 C++ 中,没有。它依赖于实现和/或平台。
在其他一些语言中,是的。例如,在 Java 中,>>运算符被精确定义为始终使用最左边的位填充(从而保留符号)。 >>>>>运算符使用 0 填充。因此,如果您想要可靠的行为,一个可能的选择是更改为另一种语言。 (尽管显然,根据您的情况,这可能不是一个选择。)
In C++, no. It is implementation and/or platform dependent.
In some other languages, yes. In Java, for example, the >> operator is precisely defined to always fill using the left most bit (thereby preserving sign). The >>> operator fills using 0s. So if you want reliable behavior, one possible option would be to change to a different language. (Although obviously, this may not be an option depending on your circumstances.)
AFAIK 整数在 C++ 中可以表示为符号量值,在这种情况下符号扩展将用 0 填充。所以你不能依赖这个。
AFAIK integers may be represented as sign-magnitude in C++, in which case sign extension would fill with 0s. So you can't rely on this.