虽然下面的两个片段在查找变量的操作上略有不同,但输出似乎仍然相同。为什么这样?
第一个代码段
#include<iostream>
using namespace std;
int main()
{
int number = 3,find;
find = number << 31;
find *= -1;
cout << find;
return 0;
}
第二个代码段
#include<iostream>
using namespace std;
int main()
{
int number = 3,find;
find = number << 31;
find *= 1;
cout << find;
return 0;
}
两个片段的输出:
-2147483648
答案 0 :(得分:4)
在两个样本中,假设32位int
,您正在调用Why does left shift operation invoke Undefined Behaviour when the left side operand has negative value?中指出的未定义行为
为什么呢?因为number
是签名的int
,具有32位存储空间。 (3<<31)
在该类型中无法表示。
一旦您处于未定义的行为区域,编译器就可以随心所欲。
(你不能依赖以下任何一个,因为它是UB - 这只是观察你的编译器似乎在做什么)。
在这种情况下,看起来编译器正在进行右移,导致0x80000000
作为二进制表示。这恰好是INT_MIN
的二进制补码表示。所以第二个片段并不奇怪。
为什么第一个输出相同的东西?在二进制补码中,MIN_INT为-2^31
。但最大值为2^31-1
。 MIN_INT * -1
将为2^31
(如果可以表示的话)。并猜猜会有什么样的表现? 0x80000000
。回到你开始的地方!