C++ 是否定义了对有符号整数进行按位运算的结果?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11644362/
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
Are the results of bitwise operations on signed integers defined?
提问by updogliu
I know that the behavior of >>
on signed integer can be implementation dependent (specifically, when the left operand is negative).
我知道有>>
符号整数的行为可能取决于实现(特别是当左操作数为负时)。
What about the others: ~
, >>
, &
, ^
, |
?
When their operands are signed integers of built-in type (short
, int
, long
, long long
), are the results guaranteed to be the same (in terms of bit content) as if their type is unsigned?
其他的呢:~
, >>
, &
, ^
, |
? 当它们的操作数是内置类型 ( short
, int
, long
, long long
) 的有符号整数时,是否保证结果与它们的类型是无符号的一样(就位内容而言)?
采纳答案by R.. GitHub STOP HELPING ICE
For negative operands, <<
has undefined behavior and the result of >>
is implementation-defined (usually as "arithmetic" right shift). <<
and >>
are conceptually not bitwise operators. They're arithmetic operators equivalent to multiplication or division by the appropriate power of two for the operands on which they're well-defined.
对于负操作数,<<
具有未定义的行为并且结果>>
是实现定义的(通常作为“算术”右移)。<<
并且>>
在概念上不是按位运算符。它们是算术运算符,相当于对它们定义良好的操作数进行适当的 2 次幂的乘法或除法。
As for the genuine bitwise operators ^
, ~
, |
, and &
, they operate on the bit representation of the value in the (possibly promoted) type of the operand. Their results are well-defined for each possible choice of signed representation (twos complement, ones complement, or sign-magnitude) but in the latter two cases it's possible that the result will be a trap representation if the implementation treats the "negative zero" representation as a trap. Personally, I almost always use unsigned expressions with bitwise operators so that the result is 100% well-defined in terms of valuesrather than representations.
至于真正的按位运算符^
、~
、|
和&
,它们对操作数的(可能提升的)类型中的值的位表示进行操作。对于带符号表示的每种可能选择(二进制补码、一补码或符号大小),它们的结果是明确定义的,但在后两种情况下,如果实现处理“负零”,则结果可能是陷阱表示表示为陷阱。就我个人而言,我几乎总是使用带有按位运算符的无符号表达式,以便结果 100% 明确定义为值而不是表示。
Finally, note that this answer as written may only apply to C. C and C++ are very different languages and while I don't know C++ well, I understand it may differ in some of these areas from C...
最后,请注意,所写的这个答案可能仅适用于 C。C 和 C++ 是非常不同的语言,虽然我不太了解 C++,但我知道它在某些领域可能与 C 有所不同......
回答by caf
- A left shift
<<
of a negative value has undefined behaviour; - A right shift
>>
of a negative value gives an implementation-defined result; - The result of the
&
,|
and^
operators is defined in terms of the bitwise representation of the values. Three possibilities are allowed for the representation of negative numbers in C: two's complement, ones' complement and sign-magnitude. The method used by the implementation will determine the numerical result when these operators are used on negative values.
<<
负值的左移具有未定义的行为;>>
负值的右移给出实现定义的结果;&
,|
和^
运算符的结果是根据值的按位表示定义的。C 中负数的表示允许三种可能性:二的补码、一的补码和符号大小。当这些运算符用于负值时,实现使用的方法将确定数值结果。
Note that the value with sign bit 1 and all value bits zero (for two's complement and sign-magnitude), or with sign bit and all value bits 1 (for ones' complement) is explicitly allowed to be a trap representation, and in this case if you use arguments to these operators that would generate such a value the behaviour is undefined.
请注意,具有符号位 1 和所有值位为零(对于二进制补码和符号幅度)或具有符号位和所有值位 1(对于二进制补码)的值被明确允许为陷阱表示,并且在此如果您使用这些运算符的参数来生成这样的值,则行为未定义。
回答by Bo Persson
The bit content will be the same, but the resulting values will still be implementation dependent.
位内容将相同,但结果值仍将取决于实现。
You really shouldn't see the values as signed or unsigned when using bitwise operations, because that is working on a different level.
在使用按位运算时,您真的不应该将值视为有符号或无符号,因为这是在不同级别上工作的。
Using unsigned types saves you from some of this trouble.
使用无符号类型可以避免一些这种麻烦。
回答by supercat
The C89 Standard defined the behavior of left-shifting signed numbers based upon bit positions. If neither signed nor unsigned types have padding bits, the required behavior for unsigned types, combined with the requirement that positive signed types share the same representation as unsigned types, would imply that the sign bit is immediately to the left of the most significant value bit.
C89 标准定义了基于位位置左移有符号数的行为。如果有符号和无符号类型都没有填充位,则无符号类型所需的行为,加上正有符号类型与无符号类型共享相同表示的要求,将暗示符号位紧邻最高有效值位的左侧.
This, in C89, -1<<1 would be -2 on two's-complement implementations which don't have padding bits and -3 on ones'-complement implementations which don't have padding bits. If there are any sign-magnitude implementations without padding bits, -1<<1 would equal 2 on those.
这在 C89 中,-1<<1 在没有填充位的二进制补码实现上是 -2,在没有填充位的二进制补码实现上是 -3。如果有任何没有填充位的符号大小实现,-1<<1 将等于 2。
The C99 Standard changed left-shifts of negative values to Undefined Behavior, but nothing in the rationale gives any clue as to why (or even mentions the change at all). The behavior required by C89 may have been less than ideal in some ones'-complement implementations, and so it would made sense to allow those implementations the freedom to select something better. I've seen no evidence to suggest that the authors of the Standard didn't intended that quality two's-complement implementations should continue to provide the same behavior mandated by C89, but unfortunately they didn't actually say so.
C99 标准将负值的左移更改为未定义行为,但基本原理中没有提供任何关于原因的线索(甚至根本没有提到更改)。C89 要求的行为在某些补码实现中可能不太理想,因此允许这些实现自由选择更好的东西是有意义的。我没有看到任何证据表明标准的作者并不打算让高质量的二进制补码实现继续提供 C89 规定的相同行为,但不幸的是,他们实际上并没有这么说。