为什么编译程序时我的max和min int不起作用?

时间:2014-02-20 03:14:24

标签: c gcc

我不明白为什么我会收到错误:

~/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;
}

2 个答案:

答案 0 :(得分:5)

重新定义INT_MININT_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_MAXINT_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