2013-01-20 76 views
-2

任何人都可以帮助我理解以下行为。(1 << 32)和(1 << i)之间的区别其中i == 32

1 #include <iostream> 
    2 
    3 using namespace std; 
    4 
    5 main() 
    6 { 
    7  uint32_t i = 32; 
    8 
    9  // cout << "(1<<32): " << (1<<32) << endl; // - This leads to a compilation error. 
    10  cout << "(1<<32): " << (1<<i) << endl; // - This compiles and prints 1 - Why? 
    11 
    12  return 0; 
    13 } 

如果我取消注释行数9以上 - 我看到下面的编译错误(这对我来说很有意义)

BitWiseLeftShift.c++: In function 'int main()': 
BitWiseLeftShift.c++:9: warning: left shift count >= width of type 

但行号10是我的问题是。它编译成功和打印

(1<<32): 1 

东西就像一个循环位移。为什么要打印1? 我已经看到,i == 33,(1<<i)打印2.

我没有搜索论坛,找不到相关的问题。如果这是一个重复的问题 - 请帮助我一个链接。

+7

在这两种情况下它都是未定义的行为,所以推测是毫无意义的。 –

+2

C++ 11§5.8p1几乎说你只要移位等于或大于底层类型的位数,就会被洗掉。 – WhozCraig

回答

5

正如其他答案指出的那样,如果移位量大于或等于移位数据位(或负数)的大小,则结果是不确定的。

然而,为了解释你看到的行为 -

某些计算机体系结构(包括x86)治疗的移位量作为模的数据的大小被移动,所以由32移位等效于不移动在所有。换句话说,他们只是屏蔽掉高位并使用低位。

7

的移位是不合法的,但编译器只捕捉第一个:

6.5.7

整数优惠在每个操作数的执行。结果的类型为 是提升的左操作数的类型。如果 的右操作数的值为负或大于或等于提升的左操作数的宽度 ,则行为是未定义的。

+0

虽然这是真的,但它并没有解释“为什么”,我相信这是svadloori正在寻找的。 – 2013-01-20 10:13:36

+0

@superoptimizer你是对的,但我认为Paul R在上面的评论中捕获了我的确切意见:*在两种情况下它都是未定义的行为,所以推测*没有意义。 – cnicutar

+0

谢谢各位的快速讨论要点。那么这个行为应该是不确定的。我只是想知道,只要我将变量i递增1,那么(1 << i)的输出以1,2,4,8 ...时尚方式进行。那么这件事对我来说看起来很奇怪。 – Sidd

4

首先,这不是一个错误,这是一个警告。编译器在第二种情况下没有发出警告的原因是,从第一个赋值中推断出结果可能是未定义行为可能不够聪明,而在第一种情况下,常量左移32位是“显然”是编译器遇到的一个问题。

+0

我想知道为什么这是被拒绝。 +1来反击它。 – cnicutar

+0

@cnicutar谢谢。我也不知道。 – 2013-01-20 10:38:51

1

恒定偏移在常量折叠期间由pro-processor评估,而第二个偏移由大多数编译器推迟到运行时间。这将解释编译器连续传递的不同响应。

静态分析有可能确定这两者具有相同的结果,并且可以在编译期间检测到。

相关问题