c - Why does -0x80000000 + -0x80000000 == 0?



在阅读一本关于程序技巧的书时,我看到-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 的补码表示,而这个特定的程序利用了这一点。

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

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

所以当我们添加 xy ,我们得到这个:

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

由于系统上的int是 32 位,因此仅保留最低的 32 位。 这些位的值为 0。

再次注意,这实际上是未定义的行为。 它之所以有效,是因为您的机器对有符号整数使用 2 的补码表示形式,并且int是 32 位的。 这对于大多数机器/编译器来说很常见,但不是全部。

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

如果没有其他信息,结果就没有意义。如果您想要一个明确的答案,请查阅您的体系结构的类型范围,并确保赋值和算术的结果适合它们各自的类型。

相关内容

  • 没有找到相关文章

最新更新