我一直在尝试使用最低符号32位整数。我写了下面的程序:
#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
}
我用g++编译它,得到以下输出:
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
第一个惊喜是例子b)和c),表明-n
等于n
,但我理解这一点:转换为int的-n = 2³² - n = 2³¹
变成了-(2³¹)
。
然而,我无法理解示例f)。我发现一元减号运算符优先于除法(https://en.cppreference.com/w/cpp/language/operator_precedence)。我期望首先-n
被计算为n
,然后n/2
应该是负的,如例d) -但事实并非如此。
我认为我误解了操作符优先级,所以我在示例g)中添加了括号,但这没有改变任何东西。
最后,在示例h)中,我将n
更改为INT_MIN
,具有相同的值,但操作结果变为负值!
我在理解例子f)和g)时遗漏了什么?在这种情况下,n
和INT_MIN
有什么区别?我观察到的是特定于语言的,还是取决于编译器?
INT_MIN
的绝对值大于INT_MAX
的绝对值。操作-n
产生的结果不在可表示的值范围内,当n == INT_MIN
。当对有符号整数的算术运算产生一个不可表示的值时,程序的行为是未定义的。