2013-05-07 33 views
-2

你能告诉我为什么下面的代码给出了一个负值,这是由于一个无符号数a左移一个负值?如果我将正数以负值向左移,为什么会得到否定结果?

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

    } 

输出 -2147483648。

+0

可能吗?确切的重复! – 2013-05-07 07:28:24

+0

您只需要先在Google中搜索,我搜索了'c negative left shift',这是Google页面上的第一个结果。 – 2013-05-07 07:29:32

回答

5

this article

如果右操作数的值是负的或大于或等于所述推动左操作数的宽度,该行为是未定义。

所以你在做什么是未定义的行为。如果您想要预测行为,请勿移位负数位。

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,这与整数(请注意,您使用的%dprintf)与-2147483648相同。

+0

“通过0x1f模数”应该是“由0x1f掩码”或“以32为模”。 – 2013-05-07 08:05:42

+0

是的,你是对的。 – 2013-05-07 08:07:02

相关问题