I've been experimenting with the lowest signed 32-bit integer. I wrote the following program:
#include <iostream>
#include <climits>
int main() {
int n = 1<<31; //-2³¹
std::cout<<"a) n = "<< (n) <<"\n";
std::cout<<"b) -n = "<< (-n) <<"\n";
std::cout<<"c) -INT_MIN = "<< (-INT_MIN) <<"\n"; //-Woverflow printed
std::cout<<"d) n/2 = "<< (n/2) <<"\n";
std::cout<<"e) n/-2 = "<< (n/-2) <<"\n";
std::cout<<"f) -n/2 = "<< (-n/2) <<"\n";
std::cout<<"g) (-n)/2 = "<< ((-n)/2) <<"\n";
std::cout<<"h) (-INT_MIN)/2 = "<< ((-INT_MIN)/2) <<"\n"; //-Woverflow printed
}
I compiled it with g and got the following output:
a) n = -2147483648
b) -n = -2147483648
c) -INT_MIN = -2147483648
d) n/2 = -1073741824
e) n/-2 = 1073741824
f) -n/2 = 1073741824
g) (-n)/2 = 1073741824
h) (-INT_MIN)/2 = -1073741824
The first surprise are examples b) and c), showing that -n
equals n
, but I understood this: -n = 2³² - n = 2³¹
, which converted to int becomes -(2³¹)
.
However, I fail to understand example f). I found that unary minus operator has precedence over division (https://en.cppreference.com/w/cpp/language/operator_precedence). I expected that first -n
is calculated as n
, and then n/2
should be negative, as in example d) – but it is not the case.
I thought that I misunderstood the operator precedence, so I added brackets in example g), but this changed nothing.
And finally, in example h) I changed n
to INT_MIN
, which has the same value, but the result of the operation became negative!
What do I miss in understanding examples f) and g)? What is the difference between n
and INT_MIN
in this case? Is what I observe specific to the language, or may it depend on the compiler?
CodePudding user response:
The absolute value of INT_MIN
is more than the (absolute) value of INT_MAX
. The operation -n
produces a result that is outside of representable values when n == INT_MIN
. When an arithmetic operation on signed integer produces an unrepresentable value, the behaviour of the program is undefined.