C++ Why does LLONG_MIN == -LLONG_MIN

3.1k views Asked by At

In C++ if I do this:

__int64 var = LLONG_MIN;
__int64 var2 = -var;
cout << "var: "<< var << endl;
cout << "var2: "<< var2 << endl;

The output I get is:

var: -9223372036854775808
var2: -9223372036854775808

What is the part of the standard that covers this? I assume it's signed integer overflow. This was compiled using g++ (GCC) 4.7.2.

I have a subtract function and I'm writing an add function and I thought I could just do this: add( someobj &obj, long long num ) { subtract( obj, -num ); }. I think that would work if it wasn't for LLONG_MIN.

2

There are 2 answers

2
syam On BEST ANSWER

It is indeed integer overflow, and an artefact of two's complement.

On your implementation, LLONG_MIN is -9223372036854775808 which is 0x8000000000000000 in hexadecimal (I will be using this hexadecimal notation because it's easier to see what happens to the bits).

When you compute -LLONG_MIN on a system that uses two's complement, under the hood you first make a bitwise-not (yielding 0x7FFFFFFFFFFFFFFF == LLONG_MAX) then add 1 which overflows the signed integer and gives back 0x8000000000000000 == LLONG_MIN.

Note that signed integer overflow is Undefined Behaviour, so there is no guarantee that it will behave consistently on every C++ implementation.

0
Andrew On

While the other answer is correct, I don't think it explain the intuitive side of this:

LLONG_MIN ==  -2^63      == -9223372036854775808
LLONG_MAX ==   2^63 - 1  ==  9223372036854775807

I was trying to think through using LLONG_MIN as a special case for something, but then I remembered that with c++ signed integral types, the lowest value is always 1 further away from 0 than the highest value (funny, every single one of them, from byte to double, ends in -...8 and +...7!).

So, I was curious then as to what would happen if you were to negate the lowest value, since there is no equivalent for it in the positive realm; and, alas, it's counted as integer overflow (-9223372036854775808 == 9223372036854775808 > 9223372036854775807), and thus it overflows by 1 (9223372036854775807 + 1), leading us back to... -9223372036854775808!


Code:

#include <iostream>
#include <climits>
using namespace std;

int main() {
  long long l1 = LLONG_MIN;
  long long l2 = -l1; //Equivalent to l1.
  long long l3 = l1 - 1;
  long long l4 = l3 + 1;
  cout << l1 << "\n";
  cout << l2 << "\n";
  cout << l3 << "\n";
  cout << l4 << "\n";

  return 0;
}

Output:

-9223372036854775808
-9223372036854775808
 9223372036854775807
-9223372036854775808