C 积分溢出?
看看这个。编译器抱怨我有整数溢出,但是当我查看 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 的答案是该表达式的正确值! (请参阅此链接)
那么,当整数溢出时,程序如何能够产生正确的值呢?更重要的是,该表达式中为什么会出现整数溢出?
have a peek at this. The compiler is complaining that I have an integer overflow, but when I look at the C89 standard's rules for integral promotion along with the values in that expression, it seems to me that there is no overflow.
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:~$
Moreover, google confirms that the answer of 2661195264 is the correct value for that expression! (See this link)
So, how is it that the program can produce a correct value when there was integer overflow? And more importantly, how is it that there was integer overflow in that expression to begin with?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
值为
2155905024
;最大可表示的signed 32位int
是2147483647
,所以你确实产生了溢出。无论如何,它恰好给了你预期的结果(你很幸运)。请注意,您的整个初始值设定项具有 signed 类型(特别是
int
类型),因为没有任何文字带有后缀。该表达式被计算为有符号整数,然后将结果值转换为无符号整数。has the value
2155905024
; the largest representable signed 32-bitint
is2147483647
, so you have indeed produced an overflow. It happens to have given you the expected result anyway (you got lucky).Note that your entire initializer has signed type (type
int
, specifically), as none of the literals are suffixed. The expression is evaluated as a signed int, then the resulting value is converted to an unsigned integer.尽管您的常量都是正数,但它们仍然是有符号整数。您溢出了有符号整数的范围。最后一步将结果分配给变量时将其转换为无符号。
有符号和无符号运算的加法、减法和乘法的位模式是相同的。虽然在这种情况下编译器不需要提供正确的答案,但这只是最自然的结果。
Although your constants are all positive, they are still signed integers. You are overflowing the range of a signed integer. The result is converted to unsigned as the last step when it is assigned to the variable.
The bit patterns for addition, subtraction, and multiplication are identical between signed and unsigned operations. While the compiler is not required to provide the correct answer in this case, it's just the most natural result.