c中的左移位

Ale*_*exi 5 c bit-shift

我一直在做一些关于位操作的愚蠢测试,我发现了这个问题.我执行这段代码:

int main(){
  unsigned int i;
  for (i=1; i<34; i++)
  {
    unsigned long temp = i;
    unsigned long mul = 1;
    unsigned long val;
    unsigned long one = 1;

    // Way 1
    while (temp--)
      mul = mul << one;

    // Way 2
    val = (one<<i);

    printf(" \n 1<<%i \n mul: 0x%X , val: 0x%X\n",i, mul, val); 
  }
}
Run Code Online (Sandbox Code Playgroud)

当然,我知道当我> 31时,会产生溢出.我认为代码的两个部分(way1和way2)应该输出相同的结果.但我得到了这个(最后):

 /* ... correct results from i=1 to i=31 ... */
 1<<30 
 mul: 0x40000000 , val: 0x40000000 

 1<<31 
 mul: 0x80000000 , val: 0x80000000 

 1<<32 
 mul: **0x0** , val: **0x1** 

 1<<33 
 mul: **0x0** , val: **0x2**
Run Code Online (Sandbox Code Playgroud)

为什么,如果两个指令都是左移,程序会产生不同的输出?似乎part way2产生了一个圆转换,但我不知道为什么,我真的认为"mul"总是得到正确的值.

我在Intel 32bits机器下编译,gcc版本4.4.7

Aif*_*Aif 9

可能是因为那是未定义的行为?根据§6.5.7:

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


mas*_*oud 2

的情况下

val = (one<<i);
Run Code Online (Sandbox Code Playgroud)

igets 大于或等于 32 时,行为未定义。

 

但是,如果

while (temp--)
   mul = mul << one;
Run Code Online (Sandbox Code Playgroud)

对于超过 32 次的移位,它将移位为零,并且结果被定义(零)。