为什么`1<< 32`和`int i = 32; 1<<我显示不同的结果?这是一个错误或功能吗?

时间:2016-04-10 13:14:04

标签: c++

代码如下所示。我在VS,clang ++和G ++上测试过它。所有这些都表明1 << 321 << i(其中我是32)是不同的。我看了一下组装。看起来编译器在编译时计算1 << 32的结果。我认为这种不一致应该是一个错误,或者它只是C ++的另一个未定义的行为。

#include <iostream>

int main(int argc, char *argv[])
{
    std::cout << (1 << 32) << std::endl;
    int i = 32;
    std::cout << (1 << i) << std::endl;
    return 0;
}

结果:

clang++:
1 << 32:73832
1 << i:1
g++:
1 << 32:73832
1 << i:1

3 个答案:

答案 0 :(得分:8)

  

std :: cout&lt;&lt; (1 <&lt; 32)&lt;&lt;的std :: ENDL;

如果int是您系统上的4个字节,则为undefined behavior。从标准(关于移位运算符的部分):

  

结果的类型是提升的左操作数的类型。该   如果右操作数为负数,或更高,则行为未定义   大于或等于提升的左操作数的位数。

答案 1 :(得分:3)

C ++标准说

  

E1 << E2的值为E1左移E2位位置;空位是零填充的。如果E1具有unsigned类型,则结果的值为E1×2^E2,比结果类型中可表示的最大值减少一个模数。否则,如果E1具有signed类型且非负值,并且E1×2^E2在结果类型中可表示,那么这就是结果值; 否则,行为未定义

然后

  

结果的类型是提升的左操作数的类型。 如果右操作数为负数,或者大于或等于提升左操作数的位数长度,则行为未定义。

在这种情况下,你不应该期待任何好事。

答案 2 :(得分:2)

<<的两个操作数均为int s,因此结果为int。如果int最大为32位宽,则在两种情况下都会发生有符号整数溢出;有符号整数溢出始终在C和C ++中都有未定义的行为。

然而,许多人错误地认为未定义的行为意味着结果是某些未指定的int&#34;或者在他们的平台上,结果是1 << 32 (mod 2³²) ;但事实是,在64位平台上,编译器倾向于使用64位寄存器进行32位计算,因为知道计算永远不会在符合程序中溢出,因此在未定义行为的情况下,实际结果也可以是值它甚至不适合32位变量!