C++ 右移和有符号整数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7522346/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:04:11  来源:igfitidea点击:

Right shift and signed integer

c++bit-shiftplatform-specific

提问by Anne Quinn

On my compiler, the following pseudo code (values replaced with binary):

在我的编译器上,以下伪代码(用二进制替换的值):

sint32 word = (10000000 00000000 00000000 00000000);
word >>= 16;

produces a wordwith a bitfield that looks like this:

生成一个word带有如下所示的位域的 :

(11111111 11111111 10000000 00000000)

My question is, can I rely on this behaviour for all platforms and C++ compilers?

我的问题是,我可以在所有平台和 C++ 编译器上依赖这种行为吗?

回答by Andrew Clark

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

来自以下链接:
INT34-C。不要将表达式移位负位数或大于或等于操作数中存在的位数

Noncompliant Code Example (Right Shift)
The result of E1 >> E2is E1right-shifted E2bit positions. If E1has an unsigned type or if E1has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1has a signed type and a negative value, the resulting value is implementation defined and can be either an arithmetic (signed) shift:
Arithmetic (signed) shift
or a logical (unsigned) shift:
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.

不合规的代码示例(右移)
结果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;

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.

对右移是作为算术(有符号)移位还是逻辑(无符号)移位进行假设也会导致漏洞。参见建议INT13-C。仅在无符号操作数上使用按位运算符

回答by R. Martinho Fernandes

No, you can't rely on this behaviour. Right shifting of negative quantities (which I assume your example is dealing with) is implementation defined.

不,你不能依赖这种行为。负数量的右移(我假设您的示例正在处理)是实现定义的。

回答by Keith Irwin

In C++, no. It is implementation and/or platform dependent.

在 C++ 中,没有。它取决于实现和/或平台。

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.)

在其他一些语言中,是的。例如,在 Java 中,>> 运算符被精确定义为始终使用最左边的位填充(从而保留符号)。>>> 运算符使用 0 填充。因此,如果您想要可靠的行为,一个可能的选择是更改为不同的语言。(尽管很明显,根据您的情况,这可能不是一种选择。)

回答by Lyberta

From the latest C++20 draft:

来自最新的 C++20 草案

Right-shift on signed integral types is an arithmetic right shift, which performs sign-extension.

有符号整数类型的右移是算术右移,它执行符号扩展。

回答by CodesInChaos

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.

AFAIK 整数可以在 C++ 中表示为符号大小,在这种情况下,符号扩展将用 0 填充。所以你不能依赖这个。