执行左移32位时出现意外输出

时间:2014-07-17 07:30:52

标签: c

当我执行左移十六进制时,我输出-1作为输出,使用以下代码:

unsigned int i,j=0;
i= (0xffffffff  << (32-j));
printf("%d",i);

同样,当我将shift值更改为32时,输出为0,但我从编译器收到警告(left shift count >= width of type)

unsigned int i,j=32;
i= (0xffffffff  << (32));
printf("%d",i);

我在两种情况下都期望得到相同的结果(即0),但是为什么在#1情况下显示错误的输出而感到困惑,在#2的情况下,结果是正确的但是编译器发出警告!

32位和64位x86计算机的结果相同。

有人可以解释上面的结果吗?

2 个答案:

答案 0 :(得分:2)

对于32位整数,左对齐32或更高版本是未定义的行为。这就是错误所在。

  

C11 6.5.7按位移位运算符

     

对每个操作数执行整数提升。结果的类型是   升级的左操作数。如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为未定义。

答案 1 :(得分:2)

将32位变量移位32会产生未定义的行为。

这是由VS-2013编译器生成的程序集:

    int n = 0;
mov         dword ptr [n],0  
    int a = 0xFFFFFFFF << 32;
mov         dword ptr [a],0  
    int b = 0xFFFFFFFF << (32-n);
mov         ecx,20h  
sub         ecx,dword ptr [n]  
or          eax,0FFFFFFFFh  
shl         eax,cl  
mov         dword ptr [b],eax  

如您所见,事实上发生的事情是:

  • 当您移动常数值32时,编译器只会将结果设置为0
  • 当您按变量(例如32-nn==0)进行切换时,编译器会使用shl

shl的实际结果取决于底层架构中此操作的实现。在你的处理器上,它可能需要第二个操作数模32,因此第一个操作数被移位0。

同样,上面的描述不是由标准规定的,所以它实际上取决于使用的编译器。