2011-04-25 125 views
4

虽然下面的两个代码片段在查找变量的操作方面略有差异,但输出结果似乎相同。为什么这样?代码片段差异

第一个片段

#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

+0

机器上的int大小是多少? 32位?我的猜测是,如果你将它转移了30位,那么你应该得到不同的结果。 – matcheek 2011-04-25 09:13:59

+1

请参阅此[问题](http://stackoverflow.com/questions/3784996/why-does-left-shift-operation-invoke-undefined-behaviour-when-the-left-side-opera)。你正在调用未定义的行为。 – Mat 2011-04-25 09:15:41

+0

@ matcheek:是的,它是32,但无法弄清楚如果将问题的目标更改为30,问题的目标如何得到满足。 – NirmalGeo 2011-04-25 09:18:21

回答

4

在这两个样本后,假设32位int S,你是在调用未定义行为作为Why does left shift operation invoke Undefined Behaviour when the left side operand has negative value?

为什么指出?因为number是带有32位存储的签名int(3<<31)在该类型中不可表示。

一旦你处于未定义的行为领域,编译器可以随心所欲。

(你不能依赖以下任何因为它是UB - 这只是你的编译器看起来在做什么的观察)。

在这种情况下,它看起来像编译器正在做右移,导致0x80000000作为二进制表示。这恰好是INT_MIN的二进制补码表示。所以第二个片段并不奇怪。

为什么第一个输出的是同样的东西?在二进制补码中,MIN_INT将是-2^31。但最大值是2^31-1MIN_INT * -1将是2^31(如果它是可表示的)。并猜测会有什么代表性? 0x80000000。回到你开始的地方!