The following C/C++ code:
long long foo = -9223372036854775808LL; // -2^63
compiles (g++) with the warning
integer constant is so large that it is unsigned.
clang++ gives a similar warning.
Thanks to this bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661. I now understand why GCC gives this warning. Unfortunately, the response to the bug report didn't explain the reason for this behaviour very well.
Questions:
This has to do with how the type of integer constants is defined.
First, as mentioned in the gcc bug report, -9223372036854775808LL
is actually two tokens: the unary -
operator and the integer constant 9223372036854775808LL
. So the warning applies only to the latter.
Section 6.4.4.1p5 of the C standard states:
The type of an integer constant is the first of the corresponding list in which its value can be represented.
Based on this, a decimal integer constant with no suffix will have type int
, long
, or long long
based on the value. These are all signed types. So anything value small enough to fit in an 8 bit or 16 bit type still has type int
, and a value too large for a 32 bit signed int will have type long
or long long
depending on the size of the type on that system. The same goes for a constant with the LL
suffix, but only the long long
type is tried.
The warning comes up because the value you're using doesn't fit in the above type list. Any lesser value will result in the value having a signed type meaning there's no conversion to unsigned.
To fix this, you'll need to use an absolute value one less that what you're using as the actual constant, then subtract 1:
long long foo = -9223372036854775807LL - 1