I'm doing some math, then printing a signed long integer like so:
file1.c
#include <stdio.h>
int main (int argc, char *argv[])
{
long my_signed_integer = 9999L * 9999L * 9999L * 9999L;
printf("This is my signed integer %ld.\n", my_signed_integer);
return 0;
}
Makefile
CFLAGS=-Wall -g
all: file1
clean:
rm -f file1
I was trying to see how far I could go without my compiler throwing me an error, adding one more 9999L to the multiplication each time, then running:
make
./file1.c
To see what happens.
4 Times
When using 9999L 4 times (like in the example above), I get:
This is my signed integer 9996000599960001.
Without any warning.
5 Times
Using 9999L 5 times, I get 1 warning:
warning: overflow in expression; result is 7716289630452291919 with type 'long'
[-Winteger-overflow]
But the file still compiles, and the eventual result is:
This is my signed integer 7716289630452291919.
6 Times
Using 9999L 6 times, I get 2 warnings - one with a negative number:
warning: overflow in expression; result is 7716289630452291919 with type 'long'
[-Winteger-overflow]
long my_signed_integer = 9999L * 9999L * 9999L * 9999L * 9999L * 9999L;
^
warning: overflow in expression; result is -7550445434587511647 with type 'long'
[-Winteger-overflow]
long my_signed_integer = 9999L * 9999L * 9999L * 9999L * 9999L * 9999L;
Alas, the files still compiles, and the result is:
This is my signed integer -7550445434587511647.
And this pattern continues as I add more and more integers - I get another warning every time.
First, can someone explain why doesn't the compiler just crash and refuse to compile the file? There's obviously an overflow - why is this tolerated, and other cases - such as multiplying very large numbers - crash it?
Also, why is the eventual result a negative integer?
Overflow of signed integer types is undefined behavior as per the C standard. So the compiler is free to generate whatever behavior it wishes. This also means it is free to generate a warning or not.
In practice, on an hosted implementation using 2's complement representation for integers, an overflow will behave as though the arguments are unsigned (and therefore an reduced modulo 2^(bit-length)) and the result interpreted as signed.
In your particular case it seems that long is a 64-bit type. So multiplying 9999L by itself 4 times fits within that type, but any more and you have overflow. The values you're getting are the lowest 64 bits of the result interpreted as a signed long.
In the case of 5 times, the high order bit happens to not be set, so the result displays at positive. In the case of 6 times, the high order bit is set, so it displays as negative.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With