我知道>>
on 有符号整数的行为可能取决于实现(特别是当左操作数为负时)。
其他的呢:~
, >>
, &
, ^
, |
? 当它们的操作数是内置类型 ( short
, int
, long
, long long
) 的有符号整数时,是否保证结果与它们的类型是无符号的一样(就位内容而言)?
我知道>>
on 有符号整数的行为可能取决于实现(特别是当左操作数为负时)。
其他的呢:~
, >>
, &
, ^
, |
? 当它们的操作数是内置类型 ( short
, int
, long
, long long
) 的有符号整数时,是否保证结果与它们的类型是无符号的一样(就位内容而言)?
对于负操作数,<<
具有未定义的行为,结果>>
是实现定义的(通常作为“算术”右移)。<<
并且>>
在概念上不是按位运算符。它们是算术运算符,相当于对其定义明确的操作数乘以适当的 2 次方的乘法或除法。
至于真正的按位运算符^
、~
、|
和&
,它们对操作数(可能提升的)类型中值的位表示进行操作。他们的结果对于有符号表示的每种可能选择(二进制补码、一个补码或符号幅度)都是明确定义的,但在后两种情况下,如果实现处理“负零”,则结果可能是陷阱表示表示为陷阱。就个人而言,我几乎总是将无符号表达式与按位运算符一起使用,以便结果在值而非表示方面是 100% 明确定义的。
最后,请注意,所写的这个答案可能仅适用于 C。C 和 C++ 是非常不同的语言,虽然我不太了解 C++,但我知道它在某些领域可能与 C 不同......
<<
负值的左移具有未定义的行为;>>
负值的右移给出实现定义的结果;&
的结果是根据值的按位表示来定义的。在 C 中允许表示负数的三种可能性:二进制补码、二进制补码和符号大小。当这些运算符用于负值时,实现使用的方法将确定数值结果。|
^
请注意,符号位为 1 且所有值位为零(对于二进制补码和符号幅度)或符号位和所有值位为 1(对于一个补码)的值被明确允许为陷阱表示,并且在此如果您对这些运算符使用会生成此类值的参数,则行为未定义。
位内容将相同,但结果值仍将取决于实现。
使用按位运算时,您真的不应该将值视为有符号或无符号,因为这是在不同的级别上工作的。
使用无符号类型可以让您避免一些麻烦。
C89 标准定义了基于位位置左移有符号数的行为。如果有符号和无符号类型都没有填充位,则无符号类型所需的行为,加上正符号类型与无符号类型共享相同表示的要求,意味着符号位紧邻最高有效值位的左侧.
这在 C89 中,-1<<1 在没有填充位的二进制补码实现上为 -2,在没有填充位的二进制补码实现上为 -3。如果有任何没有填充位的符号幅度实现,则 -1<<1 将等于 2。
C99 标准将负值的左移更改为未定义行为,但基本原理中没有任何线索说明原因(甚至根本没有提及更改)。C89 要求的行为在某些补码实现中可能不太理想,因此允许这些实现自由选择更好的东西是有意义的。我没有看到任何证据表明标准的作者并不打算让高质量的二进制补码实现继续提供 C89 规定的相同行为,但不幸的是,他们实际上并没有这么说。