为什么(1 << 31)>> 31导致-1?

the*_*ang 3 c c++ bit-shift

int z = 1;
z <<= 31;
z >>= 31;
printf ("%d\n",z);
Run Code Online (Sandbox Code Playgroud)

当我运行代码时z=-1,为什么?

Ale*_*exD 9

int z = 1;
z <<= 31;
Run Code Online (Sandbox Code Playgroud)

假设使用了int32位且使用了二进制补码表示,左移位是C中未定义的行为,因为结果如果在int类型中不可表示.从标准:

E1 << E2的结果是E1左移E2位位置

...

如果E1具有带符号类型和非负值,并且E1×2 E2可在结果类型中表示,那么这就是结果值; 否则,行为未定义.

在实践中,它很可能导致0x80000000,被视为负数.

整数的右移是实现定义的行为:

E1 >> E2的结果是E1右移E2位位置.

...

如果E1具有带符号类型和负值,则结果值是实现定义的.


C++中,左移是以类似的方式定义,直到C++ 14,正如@TC所提到的(或者,有一些限制,甚至可能是直到C++ 11,如@MattMcNabb所写).

但即使定义了左移并且0x8000000是预期值,负数的右移结果仍然是实现定义的.


tan*_*grs 5

是的,移位有符号整数和负数是我相信的实现定义.

当你向右移动时,你的实现可能会进行符号位扩展.

因此,不是从左侧移动零,而是在符号位中移位.z <<= 31;可能是将符号位设置为1,然后z >>= 31;从左侧移位,所以最终得到的位模式0xFFFFFFFF被解释为-1平台上的值(可能使用两个补码).