位移和分配

new*_*mer 4 c c++ bit-shift

这有点让我发疯.

int a = 0xffffffff;
int b = 32;
cout << (a << b) << "\n";
cout << (0xffffffff << 32) << "\n";
Run Code Online (Sandbox Code Playgroud)

我的输出是

-1
0
Run Code Online (Sandbox Code Playgroud)

为什么我没有得到

0
0
Run Code Online (Sandbox Code Playgroud)

dus*_*uff 10

当您将值移位不小于其大小的位数时(例如,32位整数为32位或更多位),会发生未定义的行为.您刚刚遇到了一个未定义行为的示例.


Jim*_*ter 10

简短的回答是,由于您使用的是32位实现int,因此语言标准称32位移位是未定义的行为.C标准(第6.5.7节)和C++标准(第5.8节)都说

如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为未定义.

但如果你想知道原因:

许多计算机都有一条指令可以移动寄存器中的值,但硬件只处理实际需要的移位值.例如,当移位32位字时,仅需要5位来表示0 ... 31的移位值,因此硬件可能忽略更高阶位,并且在*86机器上(8086除外).因此,编译器实现可以只使用该指令而不生成额外的代码来检查移位值是否太大,C标准的作者(其中许多代表编译器供应商)裁定转移大量的结果是未定义的.

你的第一次转换是在运行时执行的,它遇到了这种情况......你的机器只考虑b的低位5位,它们是0,所以不会发生转换.第二次转换是在编译时完成的,编译器以不同方式计算值,实际上是32位移位.

如果您想要移动的数量可能大于您正在移动的事物中的位数,则需要自己检查值的范围.一种可行的方法是

#define LEFT_SHIFT(a, b) ((b) >= CHAR_BIT * sizeof(a)? 0 : (a) << (b))
Run Code Online (Sandbox Code Playgroud)