为什么-0x80000000 + -0x80000000 == 0?

时间:2016-07-10 12:10:37

标签: c integer-overflow

在阅读有关程序设计技巧的书时,我看到-0x80000000 + -0x80000000 = 0.这对我没有意义所以我在下面编写了一个快速的C程序来测试,答案确实是0:

#include <stdio.h>

int main()
{
    int x = -0x80000000;
    int y = -0x80000000;

    int z = x + y;

    printf("Z is: %d", z);
    return 0;
}

任何人都可以解释为什么?我看到有关溢出的内容,但我看不到溢出如何导致0而不是异常或其他错误。我什么都没有警告。

2 个答案:

答案 0 :(得分:2)

这里发生的是有符号整数溢出,即undefined behavior,因为没有定义有符号整数的精确表示。

然而,在实践中,大多数机器使用2的有符号整数的补码表示,并且这个特定的程序利用了它。

0x80000000是无符号整数常量。 -否定它,将表达式更改为signed。假设您的系统上int为32位,则此值仍然适合。实际上,它是带符号的32位int可以容纳的最小值,并且此数字的十六进制表示恰好是0x80000000

在2的补码表示中添加数字时,它具有您无需担心符号的功能。它们的添加方式与无符号数字完全相同。

因此,当我们添加xy时,我们会得到:

   0x80000000
+  0x80000000
-------------
  0x100000000

因为系统上的int是32位,所以只保留最低的32位。并且这些位的值为0。

再次注意,这实际上是未定义的行为。它的工作原理是因为你的机器对有符号整数使用2的补码表示,而int是32位。这对于大多数机器/编译器来说很常见,但不是全部。

答案 1 :(得分:1)

您所看到的是很多实现定义的行为,很可能在运行时触发未定义的行为。如果没有关于你和书籍作家架构的详细信息,就不可能知道。

如果没有其他信息,结果就没有意义。如果您想要一个明确的答案,请参考您的架构的类型范围,并确保分配和算术的结果符合各自的类型。