我一直在做一些关于位操作的愚蠢测试,我发现了这个问题.我执行这段代码:
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
的情况下
val = (one<<i);
Run Code Online (Sandbox Code Playgroud)
当igets 大于或等于 32 时,行为未定义。
但是,如果
while (temp--)
mul = mul << one;
Run Code Online (Sandbox Code Playgroud)
对于超过 32 次的移位,它将移位为零,并且结果被定义(零)。