为什么int e=30000000000在gcc中不是警告?

为什么int e=30000000000在gcc中不是警告?,c,gcc,integer,integer-overflow,C,Gcc,Integer,Integer Overflow,考虑以下C程序: #include <stdio.h> int main(int argc, char *argv[]) { int a = -5000000000; int b = -3000000000; int c = -1000000000; int d = 1000000000; int e = 3000000000; int f = 5000000000;

考虑以下C程序:

#include <stdio.h>

int main(int argc, char *argv[]) {
        int a = -5000000000;
        int b = -3000000000;
        int c = -1000000000;
        int d =  1000000000;
        int e =  3000000000;
        int f =  5000000000;

        printf("a = %d\n", a);
        printf("b = %d\n", b);
        printf("c = %d\n", c);
        printf("d = %d\n", d);
        printf("e = %d\n", e);
        printf("f = %d\n", f);

        return 0;
}
此编译器输出:

pvz@DESKTOP-OTTHA70:~$ gcc -Wall -o overflow overflow.c
overflow.c: In function ‘main’:
overflow.c:4:10: warning: overflow in implicit constant conversion [-Woverflow]
  int a = -5000000000;
          ^
overflow.c:5:10: warning: overflow in implicit constant conversion [-Woverflow]
  int b = -3000000000;
          ^
overflow.c:9:11: warning: overflow in implicit constant conversion [-Woverflow]
  int f =  5000000000;
           ^~~~~~~~~~
这个程序输出:

pvz@DESKTOP-OTTHA70:~$ ./overflow
a = -705032704
b = 1294967296
c = -1000000000
d = 1000000000
e = -1294967296
f = 705032704
在这台机器上,int的宽度为32位,范围为-231(-2147483648)到231-1(2147483647),包括在内

正如预期的那样,尝试将不符合范围的值放入变量会导致警告,并且该值的最高有效位会被截断,从而导致整数变量a、b、e和f中出现意外值

但是,编译器只对a、b和f发出警告,而不对e发出警告

因此,问题是,为什么gcc不警告下面这一行

int e = 3000000000;

据我所知,如果你试图将231到232-1之间的值塞进一个int中,那么这些值实际上并不是警告,这一点令人惊讶。我也怀疑这是否是一个编译器错误,因为这似乎是很久以前就发现的。这意味着这可能是有意的行为。但是为什么呢?

根据问题评论中所做的一些调查,我们发现这种行为至少可以追溯到1993年10月30日,由Richard Stallman撰写,其中包含以下提交信息:

(convert_和_check):除非迂腐,否则不要警告将0xff转换为有符号字符等

来自SVN:r5944

作者的意图似乎是为了在签名为
char
的机器上,禁止在
char
中插入大十六进制值的情况下发出警告。()

但在这样做的过程中,它也适用于任何有符号整数类型的更一般情况,也适用于十进制表示,而不仅仅是十六进制或八进制表示


在我个人看来,这可能是一个错误特性(我可能只会抑制十六进制或八进制表示的警告),但我认为,
gcc
维护人员比我更有资格做出判断。

对于
-Wall-Wextra-pedantic错误
,gcc警告所有人:在为two's Complete平台设计的代码中,故意编写一个正值,使其环绕并变为负值(例如,
int mask=0xffff0000
)的情况并不少见。gcc开发人员可能认为警告此类情况会导致太多误报。好的,检查源代码。老兄,他们有个奇怪的约定。是打印溢出警告的函数。我甚至不想解释它。太多的宏和太少的代码文档都是我喜欢的^^@Teharez我在做一些挖掘工作方面取得了一些进展,似乎除了Richard Stallman之外,没有人在1993年做出过这样的承诺。并没有任何理由支持它,这在当时的提交消息中似乎很常见。不确定这是否能让我们更接近@PervonZweigbergk:commit注释提到了
char
,这是一个很好的提示,因为这种情况在
char
中可能比在
int
中更常见。首先,有一个问题是,
char
在某些实现中是有符号的,而在其他实现中是无符号的。但是大多数程序员倾向于认为
0x7f
上面的字符值是正的而不是负的,因此
charc=0xff
确实很常见。
int e = 3000000000;