为什么 -0x80000000 + -0x80000000 == 0?
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 而不是异常或其他错误的。我没有收到任何警告或任何信息。
这里发生的是有符号整数溢出,这是 undefined behavior 因为没有定义有符号整数的确切表示。
然而实际上,大多数机器使用 2 的补码表示有符号整数,而这个特定程序利用了它。
0x80000000
是无符号整型常量。 -
否定它,将表达式更改为有符号。假设 int
在您的系统上是 32 位的,这个值仍然适合。事实上,它是一个带符号的32位int
所能容纳的最小值,而这个数的十六进制表示恰好是0x80000000
.
在用2的补码表示加法时,具有不用担心符号的特点。它们的添加方式与无符号数完全相同。
所以当我们添加 x
和 y
时,我们得到:
0x80000000
+ 0x80000000
-------------
0x100000000
因为您系统上的 int
是 32 位的,所以只保留最低的 32 位。这些位的值为 0.
再次注意,这实际上是未定义的行为。它之所以有效,是因为您的机器对有符号整数使用 2 的补码表示,而 int
是 32 位。这对大多数机器/编译器都很常见,但不是全部。
您看到的是很多实现定义的行为,很可能在运行时触发未定义的行为。如果没有关于您和本书作者架构的详细信息,就不可能知道更多。
没有附加信息,结果没有意义。如果你想要一个明确的答案,请查阅你的体系结构的类型范围,并确保赋值和算术的结果适合它们各自的类型。
在阅读一本关于编程技巧的书时,我看到 -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 而不是异常或其他错误的。我没有收到任何警告或任何信息。
这里发生的是有符号整数溢出,这是 undefined behavior 因为没有定义有符号整数的确切表示。
然而实际上,大多数机器使用 2 的补码表示有符号整数,而这个特定程序利用了它。
0x80000000
是无符号整型常量。 -
否定它,将表达式更改为有符号。假设 int
在您的系统上是 32 位的,这个值仍然适合。事实上,它是一个带符号的32位int
所能容纳的最小值,而这个数的十六进制表示恰好是0x80000000
.
在用2的补码表示加法时,具有不用担心符号的特点。它们的添加方式与无符号数完全相同。
所以当我们添加 x
和 y
时,我们得到:
0x80000000
+ 0x80000000
-------------
0x100000000
因为您系统上的 int
是 32 位的,所以只保留最低的 32 位。这些位的值为 0.
再次注意,这实际上是未定义的行为。它之所以有效,是因为您的机器对有符号整数使用 2 的补码表示,而 int
是 32 位。这对大多数机器/编译器都很常见,但不是全部。
您看到的是很多实现定义的行为,很可能在运行时触发未定义的行为。如果没有关于您和本书作者架构的详细信息,就不可能知道更多。
没有附加信息,结果没有意义。如果你想要一个明确的答案,请查阅你的体系结构的类型范围,并确保赋值和算术的结果适合它们各自的类型。