Reputation: 147
Getting this warning with my new gcc compiler 6.X version.
warning: result of '117901309 << 24' requires 52 bits to represent,
but 'int' only has 32 bits [-Wshift-overflow=]
I have defined a macro with #define CLON 0x070707FD
in my code which converts to decimal value shown above in the warning.
It seems like int
is taking 4 bytes as I am running on a 64-bit machine. But I'm not sure how it went fine on earlier gcc version, say 4.X version. Can any one please help me understanding this?
Upvotes: 1
Views: 1571
Reputation: 148
You need to specify explicit size to be used. You need to define the macro as
#define CLON 0x070707FDU
Or
#define CLON 0x070707FDL
You may refer to ULL suffix on a numeric literal.
Upvotes: 1
Reputation: 754810
The new compiler is warning you about undefined behaviour which the old compiler did not warn you about. Be grateful, and finish your upgrade by moving to GCC 7.2.0, which is the latest GA version of GCC.
The C11 standard §6.5.7 Bitwise shift operators says:
The result of
E1 << E2
isE1
left-shiftedE2
bit positions; vacated bits are filled with zeros. IfE1
has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. IfE1
has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
Since your result requires 52-bits, it is not representable in a 32-bit signed integer, and the compiler is correctly warning you that you're invoking undefined behaviour — which is something you should avoid doing.
There are many ways of fixing the problem, but perhaps this is the simplest fix — change the type of CLON
to unsigned
with the U
suffix (or you could use UL
or even ULL
if you really wanted unsigned long
or unsigned long long
results):
#define CLON 0x070707FD
#define ULON 0x070707FDU
int shift_CLON(void);
unsigned shift_ULON(void);
int shift_CLON(void)
{
return CLON << 24;
}
unsigned shift_ULON(void)
{
return ULON << 24;
}
When that code is in a file sw73.c
, you can compile it like so:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes -c sw73.c
sw73.c: In function ‘shift_CLON’:
sw73.c:9:17: error: result of ‘117901309 << 24’ requires 52 bits to represent, but ‘int’ only has 32 bits [-Werror=shift-overflow=]
return CLON << 24;
^~
cc1: all warnings being treated as errors
$
Upvotes: 4
Reputation: 17444
The size of an int
is indeed compiler/system-dependent. However, that is nothing new, so odds are that with earlier versions the code didn't do what you expect already, only that with newer versions it also issues a warning.
In order to fix that, consider using explicit bit sizes on the constant, like e.g. 117901309ll
. Which of the several ones is appropriate here depends on your use case, in any case I'd consider using an unsigned value, too.
Upvotes: 0