如果我左移一个带负值的正数,为什么会得到否定结果呢?

时间:2013-05-07 07:13:12

标签: c binary bit-shift

您能告诉我为什么以下代码会因为无符号数字a左移而带负值而产生否定结果?

    int main(void)
     {
          unsigned int a=1;
          printf("%d",a<<-1);   

     }

输出 -2147483648。

2 个答案:

答案 0 :(得分:5)

来自this article

  

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

所以你正在做的是未定义的行为。如果您想要可预测的行为,请不要移动负数位。

答案 1 :(得分:1)

除了这是未定义的行为这一事实,我们可以尝试考虑您的案例中发生的事情。但要注意,这还取决于编译器和底层机器。在这个答案中,我在x86机器上使用VC ++ 2010。

看一下代码

#include "stdafx.h"

int main(int argc, _TCHAR* argv[])
{
    unsigned int a  = 1;
    printf("%d",a<<-1);   

    a  = 1;
    printf("%d",a<<31);   
}

两个班次给出了相同的答案。为了了解发生了什么,我们需要在这种情况下查看反汇编。

010E1A4E  mov         dword ptr [a],1  
010E1A55  mov         eax,dword ptr [a]  
010E1A58  shl         eax,0FFh  
...

010E1A73  mov         dword ptr [a],1  
010E1A7A  mov         eax,dword ptr [a]  
010E1A7D  shl         eax,1Fh  
...

否定班次编译为shl eax, 0ffh。对于x86,移位指令的位移只能是8位,这就是编译器使用(-1 & 0xff) = 0xff的原因。但是指令本身会将此常量掩盖0x1f。因此,两个班次都有相同的结果。 执行移位后,结果将为0x80000000,这是整数(请注意,您在%d中使用printf)与-2147483648相同。