对于一个位表示为[Xn-1,Xn-2,……,X0]的运算数x:
左移:表达式x<<k会生成一个值,其位表示为[Xn-k-1,Xn-k-2,……,X0,0,……,0],也就是说,x向左移动k位,丢弃k个最高位,并在右端补k个0。
逻辑右移(x>>k):在左端补k个0,得到[0,……,0,Xn-1,Xn-2,……,Xk]。
算术右移(x>>k):在左端补k个最高有效位的拷贝,得到[Xn-1,……,Xn-1,Xn-1,Xn-2,……,Xk]。
C标准并没有明确定义应该使用哪种类型的右移。对于无符号数据(unsigned Type),右移必须是逻辑的;对于有符号数据,C标准并没有规定使用哪种方式的右移,而实际上,几乎所有的编译器/机器组合都对有符号数据进行算术右移。
下面是测试代码:
void ShiftLeft()
{
int i1=~0;
printf("左移16位:%x-->%x ",i1,i1<<16);
unsigned int i2=~0;
printf("左移16位:%x-->%x ",i2,i2<<16);
}
void LogicRightShift()
{
unsigned int i=~0;
printf("逻辑右移16位:%x-->%x ",i,(i>>16));//这里如果左移32位或更多位时, 可能不会得到预期的结果
}
void ArithmeticRightShift()
{
int i=~0;
printf("算术右移16位:%x-->%x ",i,(i>>16));}
void TestShift()
{
ShiftLeft();
LogicRightShift();
ArithmeticRightShift();
}
{
int i1=~0;
printf("左移16位:%x-->%x ",i1,i1<<16);
unsigned int i2=~0;
printf("左移16位:%x-->%x ",i2,i2<<16);
}
void LogicRightShift()
{
unsigned int i=~0;
printf("逻辑右移16位:%x-->%x ",i,(i>>16));//这里如果左移32位或更多位时, 可能不会得到预期的结果
}
void ArithmeticRightShift()
{
int i=~0;
printf("算术右移16位:%x-->%x ",i,(i>>16));}
void TestShift()
{
ShiftLeft();
LogicRightShift();
ArithmeticRightShift();
}
输出结果:
左移16位:ffffffff-->ffff0000
左移16位:ffffffff-->ffff0000
逻辑右移16位:ffffffff-->ffff
算术右移16位:ffffffff-->ffffffff
Press any key to continue . . .