为什么 gcc 没有正确添加 tmin + tmin?

Why does gcc not add tmin + tmin correctly?

当我发现这个奇怪的东西时,我一直在玩按位运算和二进制补码。

#include <stdio.h>
int main ()
{
    int tmin = 0x80000000;
    printf("tmin + tmin: 0x%x\n", tmin + tmin);
    printf("!(tmin + tmin): 0x%x\n", !(tmin + tmin));
}

以上代码产生以下输出

tmin + tmin: 0x0
!(tmin + tmin): 0x0

为什么会这样?

0x80000000二进制是

0b10000000000000000000000000000000

当您将两个 0x80000000 相加时,

    |<-          32bits          ->|
  0b10000000000000000000000000000000
+ 0b10000000000000000000000000000000
------------------------------------
 0b100000000000000000000000000000000
    |<-          32bits          ->|

然而,int 在你的机器上似乎有 32 位,所以只保留低 32 位,这意味着你的结果中的 1 被默默地丢弃。这称为 Integer Overflow.

另请注意,在 C 中,有符号(与无符号相对,即 unsigned int)整数溢出实际上是 undefined behavior, which is why !(tmin + tmin) gives 0x0 instead of 0x1. See this blog post,例如,由于另一个未定义的行为,变量既为真又为假,即未初始化的变量。