代码段中的差异

时间:2011-04-25 09:00:17

标签: c++

虽然下面的两个片段在查找变量的操作上略有不同,但输出似乎仍然相同。为什么这样?

第一个代码段

    #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

(根据Ideone:12

1 个答案:

答案 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-1MIN_INT * -1将为2^31(如果可以表示的话)。并猜猜会有什么样的表现? 0x80000000。回到你开始的地方!