你能告诉我为什么下面的代码给出了一个负值,这是由于一个无符号数a
左移一个负值?如果我将正数以负值向左移,为什么会得到否定结果?
int main(void)
{
unsigned int a=1;
printf("%d",a<<-1);
}
输出 -2147483648。
你能告诉我为什么下面的代码给出了一个负值,这是由于一个无符号数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
。因此两个班次都有相同的结果。 执行换档后,结果将为0x80000000
,这与整数(请注意,您使用的%d
在printf
)与-2147483648相同。
“通过0x1f模数”应该是“由0x1f掩码”或“以32为模”。 – 2013-05-07 08:05:42
是的,你是对的。 – 2013-05-07 08:07:02
可能吗?确切的重复! – 2013-05-07 07:28:24
您只需要先在Google中搜索,我搜索了'c negative left shift',这是Google页面上的第一个结果。 – 2013-05-07 07:29:32