Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signed long integer becomes negative as it grows?

Tags:

c

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?

like image 634
Tom Granot Avatar asked Nov 29 '25 06:11

Tom Granot


1 Answers

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.

like image 131
dbush Avatar answered Nov 30 '25 19:11

dbush



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!