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?

+3


source to share


1 answer


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.

+6


source







All Articles