我知道对有符号整数进行位右移运算 >>
的行为可能依赖于具体的实现(特别是当左操作数为负数时)。
那其他运算符呢:~
、>>
、&
、^
、|
?如果它们的操作数是内置类型的有符号整数(short
、int
、long
、long long
),结果是否保证与其无符号类型在比特内容上相同?
我知道对有符号整数进行位右移运算 >>
的行为可能依赖于具体的实现(特别是当左操作数为负数时)。
那其他运算符呢:~
、>>
、&
、^
、|
?如果它们的操作数是内置类型的有符号整数(short
、int
、long
、long long
),结果是否保证与其无符号类型在比特内容上相同?
对于负操作数,<<
的行为未定义,>>
的结果是实现定义的(通常作为“算术”右移)。<<
和>>
概念上不是按位运算符。它们是算术运算符,对于其上定义良好的操作数等效于乘以或除以相应的二次幂。
至于真正按位运算符^
、~
、|
和&
,它们在操作数的(可能被提升的)类型的位表示中起作用。它们的结果对于每种可能的有符号表示(二进制补码、反码或原码)都是定义良好的,但在后两种情况下,如果实现将“负零”表示视为陷阱,则可能会导致结果成为陷阱表示。个人而言,我几乎总是使用无符号表达式与按位运算符一起使用,这样结果在值方面是100%定义良好的,而不仅仅是在表示方面。
最后,请注意,本答案所述内容可能仅适用于C。C和C++是非常不同的语言,虽然我不熟悉C ++,但我了解它在一些这些方面可能与C不同...
~INT_MAX
也可以成为陷阱表示。 - caf~~INT_MAX == INT_MIN
。 - cafINT_MIN==-INT_MAX
。:-( - R.. GitHub STOP HELPING ICE<<
,其行为未定义;>>
,会得到一个实现定义的结果;&
、|
和 ^
运算符的结果是根据数值的位表示来定义的。在 C 语言中,负数有三种可能的表示形式:二进制补码、反码和原码。当对负数使用这些运算符时,所使用的实现方法将决定数值结果。请注意,对于二进制补码和原码,带有符号位为 1 且所有数值位都为零的值,或者带有符号位和所有数值位都为 1(对于反码)的值被明确允许作为陷阱表示法。 在这种情况下,如果您使用这些运算符的参数会生成此类值,则其行为未定义。
二进制内容不会改变,但结果值仍然取决于具体实现。
在使用位运算时,你真的不应该将值视为有符号或无符号,因为那是在不同的层次上操作。
使用无符号类型可以避免一些麻烦。
>>
通常被实现为算术右移(正确地除以 2 个数字),如果是无符号数,>>
就是逻辑右移(用 0 填充)。<<
也没有什么混淆的地方,因为我们只需要将左边的位移出去(并在右边填充 0)。 - nhahtdh<<
而不是>>
? - Toby Speight