您能告诉我为什么以下代码会因为无符号数字a
左移而带负值而产生否定结果?
int main(void)
{
unsigned int a=1;
printf("%d",a<<-1);
}
输出 -2147483648。
答案 0 :(得分:5)
答案 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相同。