实例分析逻辑移位和算数移位

下面讨论整数的移位问题,包括有符号整数和无符号整数的左移和右移,其他情况可作参考。

概念:

逻辑移位:

逻辑左移:向左移位时将左边移出的高位丢弃,将右边空出的低位补0
逻辑右移:向右移位时将右边移出的低位丢弃,将左边空出的高位补0

算数移位:

算数左移:向左移位时将左边移出的高位丢弃,将右边空出的低位补0
算数右移:向右移位时将右边移出的低位丢弃,将左边空出的高位补0,最高位上保留符号位

实例:

#include "stdio.h"

int main()
{
	signed int positive_val = 10;
	signed int negative_val = -10;
	unsigned int unsigned_val = 10;

	int positive_sleft = positive_val << 1;
	int negative_sleft = negative_val << 1;
	int unsigned_sleft = unsigned_val << 1;

	int positive_sright = positive_val >> 1;
	int negative_sright = negative_val >> 1;
	int unsigned_sright = unsigned_val >> 1;

	printf("positive_sleft = %d\n", positive_sleft);
	printf("negative_sleft = %d\n", negative_sleft);
	printf("unsigned_sleft = %d\n", unsigned_sleft);
	printf("positive_sright = %d\n", positive_sright);
	printf("negative_sright = %d\n", negative_sright);
	printf("unsigned_sright = %d\n", unsigned_sright);

	return 0;
}

输出为:

positive_sleft = 20
negative_sleft = -20
unsigned_sleft = 20
positive_sright = 5
negative_sright = -5
unsigned_sright = 5
请按任意键继续. . .

汇编指令中,
shl:逻辑左移,
shr:逻辑右移,
sal:算术左移,
sar:算术右移,

上述源码的汇编代码为

#include "stdio.h"

int main()
{
000813C0  push        ebp  
000813C1  mov         ebp,esp  
000813C3  sub         esp,12Ch  
000813C9  push        ebx  
000813CA  push        esi  
000813CB  push        edi  
000813CC  lea         edi,[ebp-12Ch]  
000813D2  mov         ecx,4Bh  
000813D7  mov         eax,0CCCCCCCCh  
000813DC  rep stos    dword ptr es:[edi]  
	signed int positive_val = 10;
000813DE  mov         dword ptr [positive_val],0Ah  
	signed int negative_val = -10;
000813E5  mov         dword ptr [negative_val],0FFFFFFF6h  
	unsigned int unsigned_val = 10;
000813EC  mov         dword ptr [unsigned_val],0Ah  

	int positive_sleft = positive_val << 1;
000813F3  mov         eax,dword ptr [positive_val]  
000813F6  shl         eax,1  
000813F8  mov         dword ptr [positive_sleft],eax  
	int negative_sleft = negative_val << 1;
000813FB  mov         eax,dword ptr [negative_val]  
000813FE  shl         eax,1  
00081400  mov         dword ptr [negative_sleft],eax  
	int unsigned_sleft = unsigned_val << 1;
00081403  mov         eax,dword ptr [unsigned_val]  
00081406  shl         eax,1  
00081408  mov         dword ptr [unsigned_sleft],eax  

	int positive_sright = positive_val >> 1;
0008140B  mov         eax,dword ptr [positive_val]  
0008140E  sar         eax,1  
00081410  mov         dword ptr [positive_sright],eax  
	int negative_sright = negative_val >> 1;
00081413  mov         eax,dword ptr [negative_val]  
00081416  sar         eax,1  
00081418  mov         dword ptr [negative_sright],eax  
	int unsigned_sright = unsigned_val >> 1;
0008141B  mov         eax,dword ptr [unsigned_val]  
0008141E  shr         eax,1  
00081420  mov         dword ptr [unsigned_sright],eax  

	printf("positive_sleft = %d\n", positive_sleft);
00081423  mov         esi,esp  
00081425  mov         eax,dword ptr [positive_sleft]  
00081428  push        eax  
00081429  push        85858h  
0008142E  call        dword ptr ds:[89114h]  
00081434  add         esp,8  
00081437  cmp         esi,esp  
00081439  call        __RTC_CheckEsp (081136h)  
	printf("negative_sleft = %d\n", negative_sleft);
0008143E  mov         esi,esp  
00081440  mov         eax,dword ptr [negative_sleft]  
00081443  push        eax  
00081444  push        85874h  
00081449  call        dword ptr ds:[89114h]  
0008144F  add         esp,8  
00081452  cmp         esi,esp  
00081454  call        __RTC_CheckEsp (081136h)  
	printf("unsigned_sleft = %d\n", unsigned_sleft);
00081459  mov         esi,esp  
0008145B  mov         eax,dword ptr [unsigned_sleft]  
0008145E  push        eax  
0008145F  push        85890h  
00081464  call        dword ptr ds:[89114h]  
0008146A  add         esp,8  
0008146D  cmp         esi,esp  
0008146F  call        __RTC_CheckEsp (081136h)  
	printf("positive_sright = %d\n", positive_sright);
00081474  mov         esi,esp  
00081476  mov         eax,dword ptr [positive_sright]  
00081479  push        eax  
0008147A  push        858ACh  
0008147F  call        dword ptr ds:[89114h]  
00081485  add         esp,8  
00081488  cmp         esi,esp  
0008148A  call        __RTC_CheckEsp (081136h)  
	printf("negative_sright = %d\n", negative_sright);
0008148F  mov         esi,esp  
00081491  mov         eax,dword ptr [negative_sright]  
00081494  push        eax  
00081495  push        858C8h  
0008149A  call        dword ptr ds:[89114h]  
000814A0  add         esp,8  
000814A3  cmp         esi,esp  
000814A5  call        __RTC_CheckEsp (081136h)  
	printf("unsigned_sright = %d\n", unsigned_sright);
000814AA  mov         esi,esp  
000814AC  mov         eax,dword ptr [unsigned_sright]  
000814AF  push        eax  
000814B0  push        858E4h  
000814B5  call        dword ptr ds:[89114h]  
000814BB  add         esp,8  
000814BE  cmp         esi,esp  
000814C0  call        __RTC_CheckEsp (081136h)  

	return 0;
000814C5  xor         eax,eax  
}
000814C7  pop         edi  
000814C8  pop         esi  
000814C9  pop         ebx  
000814CA  add         esp,12Ch  
000814D0  cmp         ebp,esp  
000814D2  call        __RTC_CheckEsp (081136h)  
000814D7  mov         esp,ebp  
000814D9  pop         ebp  
000814DA  ret  

结论:

左移:有符号整数和无符号整数的左移都是逻辑左移
右移:有符号整数的右移是算数右移,无符号整数的右移是逻辑右移

有符号整数:左移是逻辑移位,右移是算数移位
无符号整数:左移和右移都是逻辑移位

巧记:

左移:逻辑
右移:有符号:算数,无符号:逻辑

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值