看看这个。编译器抱怨我有一个整数溢出,但是当我查看C89标准的整数提升规则以及该表达式中的值时,我觉得没有溢出。
rutski@imac:~$ cat test.c
#include <stdio.h>
#include <inttypes.h>
const uint32_t value =
(0x7F-0x00 + 1) * (256 + 256*256 + 256*256*256) +
(0xDF-0xC2 + 1) * (256 + 256*256 + 256*256*256);
int
main(void)
{
printf("value = %"PRIu32"\n", value);
return 0;
}
rutski@imac:~$ gcc -std=c89 -pedantic -Wall -Wextra test.c
test.c:5: warning: integer overflow in expression
test.c:6: warning: integer overflow in expression
test.c:6: warning: overflow in constant expression
rutski@imac:~$ ./a.out
value = 2661195264
rutski@imac:~$
此外,谷歌确认2661195264的答案是该表达式的正确值! (See this link)
那么,当整数溢出时程序如何产生正确的值呢?更重要的是,该表达式中的整数溢出是如何开始的?
答案 0 :(得分:14)
(0x7F-0x00 + 1) * (256 + 256*256 + 256*256*256)
的值为2155905024
;最大的可表示已签名 32位int
为2147483647
,因此您确实产生了溢出。它碰巧给了你预期的结果(你很幸运)。
请注意,您的整个初始值设定项都有签名类型(具体为类型int
),因为没有文字后缀。表达式被计算为signed int,然后将结果值转换为无符号整数。
答案 1 :(得分:2)
虽然你的常数都是正数,但它们仍然是有符号整数。您溢出了有符号整数的范围。将结果转换为无符号作为分配给变量的最后一步。
加法,减法和乘法的位模式在有符号和无符号运算之间是相同的。虽然在这种情况下编译器不需要提供正确的答案,但它只是最自然的结果。