Per von Zweigbergk
Per von Zweigbergk

Reputation: 189

Why is int e = 3000000000 not a warning in gcc?

Consider the following C program:

#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;
}

Consider also this environment output:

pvz@DESKTOP-OTTHA70:~$ uname -a
Linux DESKTOP-OTTHA70 4.19.104-microsoft-standard #1 SMP Wed Feb 19 06:37:35 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
pvz@DESKTOP-OTTHA70:~$ gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

And this compiler output:

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;
           ^~~~~~~~~~

And this program output:

pvz@DESKTOP-OTTHA70:~$ ./overflow
a = -705032704
b = 1294967296
c = -1000000000
d = 1000000000
e = -1294967296
f = 705032704

On this machine, an int is 32 bits wide, giving it a range of -231 (-2147483648) through 231 - 1 (2147483647) inclusive.

As expected, trying to put a value that doesn't fit within the range into the variable causes a warning, and the most significant bits of the value are truncated, leading to unexpected values in the integer variables a, b, e and f.

However, the compiler only warns us for a, b and f, and not for e.

The question therefore is, why doesn't gcc warn about the following line?

int e = 3000000000;

As far as I can tell, values from 231 to 232 - 1 surprisingly enough aren't actually warnings if you try to cram them into an int. I'm also doubtful this is a compiler bug, since this seems like something that would have been found since a long time. That means it's likely intentional behavior. But why?

Upvotes: 1

Views: 140

Answers (1)

Per von Zweigbergk
Per von Zweigbergk

Reputation: 189

From some investigation done in the question comments, we found that this behaviour dates back to at least to October 30, 1993 in this commit by Richard Stallman with this commit message:

"(convert_and_check): Don't warn converting 0xff to a signed char, etc., unless pedantic."

From-SVN: r5944

It would seem the authors intent was to suppress warnings for the case where large hexadecimal values are stuck into chars on machines where char is signed. (char can be signed or unsigned depending on implementation according to the C standard.)

But in doing so, it also did it for the more general case of any signed integer type, and also for decimal representations, not just hexadecimal or octal representations.

In my personal opinion, this is probably a misfeature (and I would probably only suppress warnings for hexadecimal or octal representations), but that's a judgement call that I think the gcc maintainers are far more qualified to make than myself.

Upvotes: 1

Related Questions