Does the sign of a long integer turn negative as it grows?
I'm doing math and then I print a long integer like this:
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 figure out how far I could get by without my compiler by dumping me with an error, adding another one 9999L
to the multiplication every time, and then running:
make
./file1.c
To see what happens.
4 times
When used 9999L
4 times (as in the example above), I get:
This is my signed integer 9996000599960001.
Without 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 end 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 are still compiled and the result is:
This is my signed integer -7550445434587511647.
And this pattern continues as I add more and more integers - each time I get a different warning.
First, can anyone explain why the compiler just won't work and doesn't want to compile the file? Obviously overflow - why does this carry over, while other cases - like multiplication of very large numbers - crash?
Also, why does it end up with a negative integer?
source to share
Significant integer types overflow undefined behavior according to the C standard. Thus, the compiler can generate any behavior it wants. This also means that it can generate a warning or not.
In practice, in a hosted implementation using 2's complement representations for integers, the overflow will behave as if the arguments were unsigned (and therefore decremented modulo 2 ^ (doss length)), and the result is interpreted as signed ...
In your specific case, it seems like long
is a 64-bit type. So multiplication 9999L
itself 4 times is fine for this type, but more and you have overflow. The values you get are the least significant 64 bits of the result, which are interpreted as signed long
.
In case of 5 times, the high order bit is not set, so the result is displayed positively. In the case of 6 times, the high order bit is set, so it is displayed as negative.
source to share