我不明白为什么我会收到错误:
~/SecureSoftware$ gcc AddNumTest.c
AddNumTest.c:11:0: warning: "INT_MAX" redefined [enabled by default]
/usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed/limits.h:121:0: note: this is the location of the previous definition
我正在寻找一种方法,在命令行中添加一个大数字时不会崩溃我的程序。
#include<stdio.h>
#include <stdlib.h>
#include <limits.h>
#define INT_MAX (2147483647)
#define INT_MIN (-2147483647)
int main(int argc, char** argv)
{
int i, TotalOfNumbers = 0;
for (i = 1; i < argc; i++)
{
TotalOfNumbers += atoi(argv[i]);
printf("Total of numbers entered = %d\n", TotalOfNumbers);
}
return 0;
}
答案 0 :(得分:5)
重新定义INT_MIN
和INT_MAX
不会改变实际限制,只会使描述它们的常量不准确。
限制基于平台的整数大小/宽度。要拥有真正不同的限制,您需要使用不同的数据类型(例如,long
而不是int
)。
如果long
不够大,您可能需要进一步向上移动到long long
;请注意,这些在C99标准之前未指定,因此您需要拥有一个相当现代的编译器。
将程序更改为使用long
而不是int
s,如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char** argv)
{
long long i, TotalOfNumbers = 0;
for (i = 1; i < argc; i++)
{
TotalOfNumbers += atoll(argv[i]);
printf("Total of numbers entered = %lld\n", TotalOfNumbers);
}
return 0;
}
答案 1 :(得分:4)
以下是将文本转换为C中的整数的正确的方式:与atoi
不同,strtol
实际上会告诉您数字是否过大,尽管在某种程度上尴尬的时尚。
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
long
reliable_atol(const char *s)
{
char *endp;
long rv;
errno = 0;
rv = strtol(s, &endp, 10);
if (errno || endp == s || *endp) {
fprintf(stderr, "number malformed or out of range: %s\n", s);
exit(1);
}
return rv;
}
在代码中使用此功能代替atoi
,并将TotalOfNumbers
更改为long
(并使用%ld
打印)。
您可能还想尝试在添加中检测溢出,但是您可以在不使用INT_MAX
或INT_MIN
的情况下执行此操作:
int main(int argc, char **argv)
{
int i;
long TotalOfNumbers = 0;
for (i = 1; i < argc; i++) {
long n = reliable_atol(argv[i]);
long sum = (long) ((unsigned long)TotalOfNumbers + (unsigned long)n);
if ((n > 0 && sum < TotalOfNumbers) || (n < 0 && sum > TotalOfNumbers)) {
fputs("numeric overflow while computing sum\n", stderr);
exit(2);
}
TotalOfNumbers = sum;
}
printf("total %ld\n", TotalOfNumbers);
return 0;
}
强制转换是必需的,因为有符号整数溢出会引发未定义的行为,但无符号整数溢出则不会。这段代码在技术上不适用于非二进制补码CPU,但几十年来没有人制造过其中的一种,而C标准继续为这种可能性提供的服务变得非常愚蠢。
如果我将上面两个代码示例放在一起,制作一个完整的程序,我会为你的测试用例得到这个:
$ gcc -O2 -Wall test.c # default mode for this CPU+OS: long is 64 bits
$ ./a.out 22220020202 45
total 22220020247
$ gcc -O2 -Wall -m32 test.c # alternative mode: long is 32 bits
$ ./a.out 22220020202 45
number malformed or out of range: 22220020202