I want to understand more about int overflow in C++ on a 64-bit system. So I would like to stick to int for my understanding without casting / extending the type to unsigned or 64-bit and I am on Intel x64 Ubuntu using VSCode with cmake.
$ g++ --version
g++ (Ubuntu 14.2.0-4ubuntu2) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
The following just shows assertion failed without the -Woverflow exception:
int i = 0x80000000;
cout << "i: " << i << ", -i: " << -i << endl; // Output: i: -2147483648, -i: -2147483648
assert(0x80000000 == -0x80000000); // OK
assert(i == -i); // XXX: assert exception. Why!?!
/*
* 0x8000_0000 + 1 = -0x7FFF_FFFF = 0x8000_0001 (Two's compliment)
* 0x8000_0000 - 1 = -0x8000_0001 = 0x7FFF_FFFF
*/
int i = 0x80000000;
int j = i + 1;
cout << i << " (0x" << hex << i << ") + 1 = " << dec << j << " 0x" << hex << j << endl;
assert(j == 0x80000001); // OK
j = i - 1;
cout << dec << i << " (0x" << hex << i << ") - 1 = " << dec << j << " 0x" << hex << j << endl;
assert(j == 0x7FFFFFFF); // XXX: assert exception. Why!?!
The following throws -Woverflow exception:
int i = 0x80000000; // numeric_limits<int>::min()
int j = 0x7FFFFFFF; // numeric_limits<int>::max()
cout << i << " - " << j << " = " << i - j << endl; // Output: "-2147483648 - 2147483647 = 1"
assert(1 == i - 0x7FFFFFFF); // XXX: integer overflow in expression of type ‘int’ results in ‘1’ [-Woverflow]
assert(1 == (i - j)); // XXX: integer overflow in expression of type ‘int’ results in ‘1’ [-Woverflow]
i = -INT_MIN; // == 0x80000000
assert(j == (i - 0x7FFFFFFF)); // XXX: integer overflow in expression of type ‘int’ results in ‘1’ [-Woverflow]
These assertions pass:
assert(1 == (int)0x80000000 - (int)0x7fffffff);
assert(1 == 0x80000000 - 0x7fffffff);
Here are my questions:
(1) Why would 0x80000000 - 0x7FFFFFFF overflow? Shouldn't it rightly yield 1?
(2) Why is the cout behaviour different from assert?
(3) Why do some throws assert exception and some -Woverflow exception?
int i=0x80000000; int j=0x7fffffff; i-jis not the same as0x80000000-0x7fffffff. The former results in a signed overflow due to the declared types ofiandj, the latter is perfectly valid operation between two unsigned integers. Your first question is asking the wrong question.-Woverflowmay be designed to work only with expressions containing variables, but that's very compiler-specific.int) of(int)0x80000000 - (int)0x7fffffff)gives undefined behaviour, soassert(1 == (int)0x80000000 - (int)0x7fffffff)is allowed to pass, it is allowed to fail, or [fortunately, rare in practice] your compiler is permitted to reformat your hard drive.