Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Integer constant is so large that it is unsigned" compiler warning rationale

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:

  • Why is no warning given for the equivalent code for a 32/16/8-bit signed integer constant?
  • GCC and Clang both give this warning, so it is clearly intentional behaviour and not just 'to make it easier to parse,' as is suggested in response to the bug report. Why?
  • Is this behaviour mandated by the C/C++ standard? Some other standard?
like image 672
jezza Avatar asked Nov 25 '20 15:11

jezza


People also ask

What is an unsigned integer constant What is the significance of declaring a constant unsigned?

Unsigned integer constant is an integer constant which has the permissible range from 0 to 65536. Thus significance of declaring a constant as unsigned almost doubles the size of the largest possible value.

What is unsigned constant in C?

Unsigned constants are written with a terminal u or U , and the suffix ul or UL indicates unsigned long . Floating-point constants contain a decimal point ( 123.4 ) or an exponent ( 1e-2 ) or both; their type is double , unless suffixed. The suffixes f or F indicate a float constant; l or L indicate a long double .


2 Answers

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.

integer constant table

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.

like image 181
dbush Avatar answered Oct 11 '22 22:10

dbush


As various more or less confused people in the bug report said, the integer constant 9223372036854775808LL is too large to fit inside a long long.

For decimal constants, the standard has a list in 6.4.4.1 (see the answer by @dbush) describing what types the compiler will try to give to an integer constant. In this case, the only valid option for type is (signed) long long and it won't fit there. Then §6 under that table kicks in:

If an integer constant cannot be represented by any type in its list, it may have an extended integer type, if the extended integer type can represent its value. /--/
If the list contains both signed and unsigned types, the extended integer type may be signed or unsigned.

Extended integer type is a fuzzy but formal term in the standard. In this case the compiler apparenty tries to squeeze the constant into a unsigned long long "extended integer type" where it fits. This isn't really guaranteed behavior but implementation-defined.

Then the unary - operator is applied to the unsigned long long which produces the warning.

This is the reason why library headers such as limits.h like to define LLONG_MIN as

#define LLONG_MIN (-9223372036854775807LL - 1)

You could do something similar to avoid this warning. Or better yet, use LLONG_MIN.

like image 24
Lundin Avatar answered Oct 11 '22 22:10

Lundin