我正在开发一个更新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
EDIT2:
在阅读了一些评论后,我将'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
最终编辑:
在阅读了更多评论之后,我发现我的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 :(得分:7)
我的猜测是您的平台有64位size_t
,并且您使用了错误的格式说明符来打印size_t
,这是undefined behavior并导致误导输出。
要print size_t
s,请在gcc和clang上使用%zu
,在MSVC上使用%Iu
。或者忘记所有这些并使用std::cout
打印结果。
在VS2015上使用%Iu
,我在64位编译器上获得的输出是
largerNum = 12
Num = 4294967295
Num + 1 = 4294967296
largerNum now = 4294967296
largerNum did not overflow: 4294967296
Is (0 < UINT_MAX)?
YES
Is (largerNum < Num)?
NO
答案 1 :(得分:1)
只需添加@ Praetorian的答案并显示类型安全的实现:
#include <iostream>
#include <limits>
int main (void) {
using std::size_t;
using std::cout;
size_t largerNum = 12;
size_t Num = std::numeric_limits<size_t>::max();
cout << "largerNum = " << largerNum << "\nNum = " << Num << "\nNum + 1 = " << Num + 1 << "\n";
largerNum = Num + 1;
cout << "largerNum now = " << largerNum << "\n";
if(largerNum < Num ){
cout << "largerNum overflowed to " << largerNum << "\n";
}
else {
cout << "largerNum did not overflow: " << largerNum << "\n";
}
cout << "Is (0 < Unsigned Maximum)?\n";
(0 < std::numeric_limits<size_t>::max())?cout << "YES\n":cout << "NO\n";
cout << "Is (largerNum < Num)?\n";
(largerNum < Num)?cout << "YES\n":cout << "NO\n";
return 0;
}
因此:'printf'在C ++中不是一个好选择,它不是类型安全的(虽然好的编译器可以识别无效的格式说明符)。另一方面,iostream运算符很麻烦(对于许多人而言)并且如果必须将输出转换为不同语言(例如:gnu getline)则很糟糕。您可以浏览网络以获取类型安全格式字符串(例如:boost :: format)