被未定义的C移位运算符行为和包装“模式空间”所迷惑

我对在article on undefined C++ behavior的Shift Operators部分中阅读的内容感到困惑.

On the ARM architecture, the shift operators always behave as if they take place in a 256-bit pattern space, regardless of the operand size–that is, the pattern repeats, or “wraps around”, only every 256 positions. Another way of thinking of this is that the pattern is shifted the specified number of positions modulo 256. Then, of course, the result contains just the least-significant bits of the pattern space.

这些表尤其奇怪:

Given a 32-bit integer with a value of 1:
+-----------------------------------+
| Shift left    ARM    x86    x64   |
+-----------------------------------+
| 32            0      1      1     |
| 48            0      32768  32768 |
| 64            0      1      1     |
+-----------------------------------+

这些价值观是什么,为什么如此重要?

shift operators不包装.根据C规范,如果将32位值左移32,则结果始终为0.(编辑:我错了,请参见答案!)那么本文的目的是什么?什么是未定义行为?

当我在x86上运行此代码时,我得到0:

printf("%d", 1 << 32);

假设this code snippet说明了此问题:

// C4293.cpp
// compile with: /c /W1
unsigned __int64 combine (unsigned lo, unsigned hi) {

    return (hi << 32) | lo;   // C4293

    // try the following line instead
    // return ( (unsigned __int64)hi << 32) | lo;
}

我希望返回的值是lo,因为程序员移开了所有的hi位.警告是很好的,因为这可能是一个错误,但是我看不到任何未定义的行为…

最佳答案
如果使用x86或x64机器指令对值进行移位,则它们将掩盖移位量,并且仅将低位用于实际移位.其他一些硬件可能不会这样做.

这就是为什么它是未定义的.

在您的文字为1的示例中<< 32,很可能是编译器计算了该值,这就是为什么它是0.在实际的x86硬件上尝试该操作,您将获得1.

转载注明原文:被未定义的C移位运算符行为和包装“模式空间”所迷惑 - 代码日志