你能告诉我为什么下面的代码由于左移a
带有负值的无符号数而给出负结果吗?
int main(void)
{
unsigned int a=1;
printf("%d",a<<-1);
}
输出 -2147483648。
除了这是未定义的行为这一事实之外,我们还可以尝试考虑在您的情况下会发生什么。但要注意,这也取决于编译器和底层机器。在这个答案中,我在 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
. 因此,两个班次具有相同的结果。执行移位后,结果将是与 -2147483648 相同的0x80000000
整数(请注意您%d
在 中使用)。printf