【发布时间】:2015-05-20 16:09:14
【问题描述】:
我正在开发一个更新 20 年前的代码的项目,其中许多问题都与整数溢出有关。我想确保我正确地测试溢出,所以我编写了一个测试程序。它的输出让我大吃一惊。这里是:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
int main (void) {
size_t largerNum,Num;
largerNum = 12;
Num = UINT_MAX;
printf("largerNum = %u\nNum = %u\nNum + 1 = %u\n", largerNum , Num, Num + 1);
largerNum = Num + 1;
printf("largerNum now = %u\n", largerNum);
if(largerNum < Num ){
printf("largerNum overflowed to %u\n", largerNum);
}
else {
printf("largerNum did not overflow: %u\n", largerNum);
}
printf("Is (0 < UINT_MAX)?\n");
(0 < UINT_MAX)?printf("YES\n"):printf("NO\n");
printf("Is (largerNum < Num)?\n");
(largerNum < Num)?printf("YES\n"):printf("NO\n");
return 0;
}
及其输出:
[afischer@susm603 /home/afischer/Fischer_Playground/overflowTest]$ main
largerNum = 12
Num = 4294967295
Num + 1 = 0
largerNum now = 0
largerNum did not overflow: 0
Is (0 < UINT_MAX)?
YES
Is (largerNum < Num)?
NO
我查看了其他一些帖子here 和here 并阅读了此paper,但它并没有使输出变得清晰。有人见过这个吗?
编辑:当我从 size_t 更改为 unsigned long 时,它可以正常工作,这不应该做任何事情。
6 int main (void) {
7
8 unsigned long largerNum,Num;
9
10 largerNum = 12;
11 Num = UINT_MAX;
12
13 printf("largerNum = %u\nNum = %u\nNum + 1 = %u\n", largerNum , Num, Num + 1);
14
15 largerNum = Num + 2;
16
17 printf("largerNum now = %u\n", largerNum);
18
19 if(largerNum < Num ){
20 printf("largerNum overflowed to %u\n", largerNum);
21 }
22 else {
23 printf("largerNum did not overflow: %u\n", largerNum);
24 }
25
26 printf("Is (0 < UINT_MAX)?\n");
27
28 (0 < UINT_MAX)?printf("YES\n"):printf("NO\n");
29
30 printf("Is (largerNum < Num)?\n");
31
32 (largerNum < Num)?printf("YES\n"):printf("NO\n");
33
34
35 printf("largerNum = %u\n", largerNum);
36 printf("Num = %u\n", Num);
37
38 return 0;
39 }
输出:
[afischer@susm603 /home/afischer/Fischer_Playground/overflowTest]$ main
largerNum = 12
Num = 4294967295
Num + 1 = 0
largerNum now = 1
largerNum overflowed to 1
Is (0 < UINT_MAX)?
YES
Is (largerNum < Num)?
YES
largerNum = 1
Num = 4294967295
编辑2:
在阅读了一些 cmets 后,我将 'UINT_MAX' 替换为 'ULONG_MAX',并且三元运算符正常运行。然后我将“size_t”更改为“unsigned long”。它仍然可以正常工作。对我来说奇怪的是,在我的机器上,“size_t”、“unsigned int”和“unsigned long”都是相同的字节数,“UINT_MAX”和“ULONG_MAX”是相同的值,但是那个三元运算符尽管一切都一样,但仍然会失败。也许不一样?这扰乱了我对 C 的理解。
对于那些感兴趣的人,工作代码:
6 int main (void) {
7 /* Can be size_t or unsigned long */
8 size_t largerNum,Num;
9
10 largerNum = 12;
11 Num = ULONG_MAX;
12
13 printf("largerNum = %u\nNum = %u\nNum + 1 = %u\n", largerNum , Num, Num + 1);
14
15 largerNum = Num + 2;
16
17 printf("largerNum now = %u\n", largerNum);
18
19 if(largerNum < Num ){
20 printf("largerNum overflowed to %u\n", largerNum);
21 }
22 else {
23 printf("largerNum did not overflow: %u\n", largerNum);
24 }
25
26 printf("Is (0 < ULONG_MAX)?\n");
27
28 (0 < ULONG_MAX)?printf("YES\n"):printf("NO\n");
29
30 printf("Is (largerNum < Num)?\n");
31
32 (largerNum < Num)?printf("YES\n"):printf("NO\n");
33
34
35 printf("largerNum = %u\n", largerNum);
36 printf("Num = %u\n", Num);
37
38 return 0;
39 }
输出:
[afischer@susm603 /home/afischer/Fischer_Playground/overflowTest]$ main
largerNum = 12
Num = 4294967295
Num + 1 = 0
largerNum now = 1
largerNum overflowed to 1
Is (0 < ULONG_MAX)?
YES
Is (largerNum < Num)?
YES
largerNum = 1
Num = 4294967295
最终编辑:
看了更多的cmets,发现我的printf()语句有误。谢谢大家的帮助,现在一切都变得更有意义了。 =D
最终代码:
6 int main (void) {
7
8 unsigned long largerNum,Num;
9
10 largerNum = 12;
11 Num = ULONG_MAX;
12
13 printf("largerNum = %zu\nNum = %zu\nNum + 1 = %zu\n", larger Num, Num, Num + 1);
14
15 largerNum = Num + 2;
16
17 printf("largerNum now = %zu\n", largerNum);
18
19 if(largerNum < Num ){
20 printf("largerNum overflowed to %zu\n", largerNum);
21 }
22 else {
23 printf("largerNum did not overflow: %zu\n", largerNum);
24 }
25
26 printf("Is (0 < ULONG_MAX)?\n");
27
28 (0 < ULONG_MAX)?printf("YES\n"):printf("NO\n");
29
30 printf("Is (largerNum < Num)?\n");
31
32 (largerNum < Num)?printf("YES\n"):printf("NO\n");
33
34
35 printf("largerNum = %zu\n", largerNum);
36 printf("Num = %zu\n", Num);
37
38 return 0;
39 }
最终输出:
[afischer@susm603 /home/afischer/Fischer_Playground/overflowTest]$ main
largerNum = 12
Num = 18446744073709551615
Num + 1 = 0
largerNum now = 1
largerNum overflowed to 1
Is (0 < ULONG_MAX)?
YES
Is (largerNum < Num)?
YES
largerNum = 1
Num = 18446744073709551615
【问题讨论】:
-
究竟哪一部分让你感到惊讶?
-
在
(0 < UINT_MAX)中,您的编译器是否认为0是int?如果是这样,(0 < 0xFFFFFFFF)是假的。 -
我认为
size_t在您的平台上是 64 位的,但您使用了错误的printf格式说明符,因此被截断。由于这也被标记为 C++,因此请使用cout进行打印,您的问题可能会消失。 -
@Praetorian 我认为你应该从中建立一个答案,
%u根本不是显示size_t的正确方式。
标签: c printf overflow operator-keyword size-t