2147483648 不是 32 位的 int,它刚好在 INT_MAX 之上,在此类平台上其值为 2147483647。
int b = 2147483648; 是实现定义的。在您的平台上,它似乎执行 32 位回绕,这是典型的二进制补码架构,但 C 标准不保证。
因此printf("%d\n", b); 输出-2147483648。
其余代码在 32 位系统上完美定义,输出 2147483649 正确且符合预期。 64 位 的操作系统在评估步骤中起着非常微妙的作用,但与实际结果几乎无关,这完全由 C 标准定义。
以下是步骤:
-
unsigned int a = 2147483650; 毫不奇怪,a 是 unsigned int,它的初始化器是 int、long int 或 long long int,具体取决于这些类型中的哪一个具有至少 32 个值位。在 Windows 和 32 位 linux 上,它将是 long long int,而在 64 位 linux 上,它将是 long int。该值在存储到unsigned int 变量时被截断为 32 位。
您可以通过添加以下代码来验证这些步骤:
printf("sizeof(2147483650) -> %d\n", (int)sizeof(2147483650));
printf(" sizeof(a) -> %d\n", (int)sizeof(a));
-
第二个定义unsigned int c = a+(-1);经历相同的步骤:
-
c 被定义为 unsigned int,并且它的初始化程序在存储到 c 时被截断为 32 位。初始化器是一个加法:
- 第一项是
unsigned int,值为2147483650U。
- 第二项是一个带括号的表达式,它对值为
1 的int 进行一元否定。因此,它是一个 int,其值为 -1,正如您正确分析的那样。
- 第二项转换为
unsigned int:转换为模232,因此值为4294967295U。
- 然后使用无符号算术执行加法,它被指定为以
unsigned int 类型的宽度为模,因此结果是unsigned int 的值为2147483649U,(6442450945 模232)
- 此
unsigned int 值存储在c 中,并使用printf("%u\n", c); 正确打印为2147483649。
如果表达式改为 2147483650 + (-1),则计算将在 64 位有符号算术中进行,类型为 long int 或 long long int,具体取决于架构,结果为 2147483649。当存储到 c 时,该值将被截断为 32 位,因此 c 的值与 2147483649 相同。
请注意,上述步骤不依赖于负值的实际表示。它们是为所有架构完全定义的,只有int 类型的宽度很重要。
您可以使用额外的代码来验证这些步骤。下面是一个完整的检测程序来说明这些步骤:
#include <limits.h>
#include <stdio.h>
int main(void) {
printf("\n");
printf(" sizeof(int) -> %d\n", (int)sizeof(int));
printf(" sizeof(unsigned int) -> %d\n", (int)sizeof(unsigned int));
printf(" sizeof(long int) -> %d\n", (int)sizeof(long int));
printf(" sizeof(long long int) -> %d\n", (int)sizeof(long long int));
printf("\n");
int b = 2147483647; // To show the maximum value of int type here is 2147483647
printf(" int b = 2147483647;\n");
printf(" b -> %d\n",b);
printf(" sizeof(b) -> %d\n", (int)sizeof(b));
printf(" sizeof(2147483647) -> %d\n", (int)sizeof(2147483647));
printf(" sizeof(2147483648) -> %d\n", (int)sizeof(2147483648));
printf(" sizeof(2147483648U) -> %d\n", (int)sizeof(2147483648U));
printf("\n");
unsigned int a = 2147483650;
printf(" unsigned int a = 2147483650;\n");
printf(" a -> %u\n", a);
printf(" sizeof(2147483650U) -> %d\n", (int)sizeof(2147483650U));
printf(" sizeof(2147483650) -> %d\n", (int)sizeof(2147483650));
printf("\n");
unsigned int c = a+(-1);
printf(" unsigned int c = a+(-1);\n");
printf(" c -> %u\n", c);
printf(" sizeof(c) -> %d\n", (int)sizeof(c));
printf(" a+(-1) -> %u\n", a+(-1));
printf(" sizeof(a+(-1)) -> %d\n", (int)sizeof(a+(-1)));
#if LONG_MAX == 2147483647
printf(" 2147483650+(-1) -> %lld\n", 2147483650+(-1));
#else
printf(" 2147483650+(-1) -> %ld\n", 2147483650+(-1));
#endif
printf(" sizeof(2147483650+(-1)) -> %d\n", (int)sizeof(2147483650+(-1)));
printf(" 2147483650U+(-1) -> %u\n", 2147483650U+(-1));
printf("sizeof(2147483650U+(-1)) -> %d\n", (int)sizeof(2147483650U+(-1)));
printf("\n");
return 0;
}
输出:
sizeof(int) -> 4
sizeof(unsigned int) -> 4
sizeof(long int) -> 8
sizeof(long long int) -> 8
int b = 2147483647;
b -> 2147483647
sizeof(b) -> 4
sizeof(2147483647) -> 4
sizeof(2147483648) -> 8
sizeof(2147483648U) -> 4
unsigned int a = 2147483650;
a -> 2147483650
sizeof(2147483650U) -> 4
sizeof(2147483650) -> 8
unsigned int c = a+(-1);
c -> 2147483649
sizeof(c) -> 4
a+(-1) -> 2147483649
sizeof(a+(-1)) -> 4
2147483650+(-1) -> 2147483649
sizeof(2147483650+(-1)) -> 8
2147483650U+(-1) -> 2147483649
sizeof(2147483650U+(-1)) -> 4