(1 <32)和(1 <1)之间的差异。

时间:2013-01-20 10:07:37

标签: c++ c

任何人都可以帮助我理解以下行为。

    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。

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

4 个答案:

答案 0 :(得分:7)

转换不合法,但编译器只捕获第一个:

  

6.5.7

     

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

答案 1 :(得分:5)

正如其他答案中所指出的,如果移位量大于或等于位移位数据的大小(或为负数),则结果是未定义的。

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

某些计算机体系结构(包括x86)将移位量视为模数被移位的数据的模数,因此移位32相当于根本不移位。换句话说,它们只是掩盖了较高的位并使用较低的位。

答案 2 :(得分:4)

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

答案 3 :(得分:1)

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

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