位移运算符似乎会进行包裹处理?

4

这是在 Windows 7 32 位系统下,使用 Visual Studio 2017 编写的 C 文件。

int i = 65536;

正如预期的那样,

i >> 0 = 65536
i >> 1 = 32768
  :
  :
i >> 16 = 1
i >> 17 to 31 = 0.

i >> 32 的结果神奇地变成了65536,为什么合法呢?

根据ISO/IEC 9899:TC2的规定,如果E1是无符号类型或者E1是有符号类型且其值非负,则E1 >> E2的结果为E1右移E2位的整数部分。如果E1是有符号类型且其值为负数,则结果取决于具体实现。我假设C++规范也是如此。


2
标准中的相关引用应该是关于将位移量超出左操作数位数的引用。 - Some programmer dude
这里并没有什么魔法,其他一些语言中,这种行为甚至是强制性的 - harold
1个回答

11

6.5.7p3

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

使用clang、gcc和icc,如果您试图按大于或等于位移值宽度的常量进行移位运算,则会获得警告,甚至不需要任何额外的命令行标志。


1
好的,那么,这是一个可怕的规范,因为他们对我引用的值做出了不合格的陈述,然后在另一段中有了限定条件。我想知道为什么他们不只是放一个情况和结果的表格。 - Swiss Frank
1
@SwissFrank 原因是不同的 CPU 有不同的行为,例如,在 x86-32bit 上只使用移位计数的最后 5 位。这意味着如果要实现跨平台,就需要进行一些额外的比较/分支/掩码操作。由于 C(和 C++)旨在成为零开销语言,像这样的事情通常会被留空未定义(或实现定义)。 - chtz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接