在单片机开发中,通常会使用左移和右移操作做快速的乘法和除法运算。
例如,将0x0001左移1位,相当于乘以2^1左移2位相当于乘以2^2,以此类推,左移n位,相当于乘以2^n。右移则相当于除以2^n。
那么对于无符号数和有符号数,对于左移和右移的操作分别是如何呢?下面通过实验来进行验证:
对于无符号数的左移和右移,代码片段如下:
void main(void){
static UINT16 sTemp;
sTemp = 0x0001;
sTemp = sTemp <<1 ;
sTemp = 0x0400;
sTemp = sTemp >> 1;
sTemp = 0xFFFF;
sTemp = sTemp >> 1;
while(1);
}
仿真运行结果:
sTemp = 0x0001;
sTemp = sTemp <<1 ;
执行左移后,sTemp值为0x0002
0000000000000001B --> 0000000000000010B
可见:无符号数左移策略是丢弃最高位,低位补0
sTemp = 0x0400;
sTemp = sTemp >> 1;
执行右移后,sTemp的值为0x0200
0000010000000000B --> 0000001000000000B
可见:无符号数执行右移策略是丢弃最低位,高位补0
sTemp = 0xFFFF;
sTemp = sTemp >> 1;
执行右移后,sTemp的值为0x7FFF
1111111111111111B --> 0111111111111111B
右移策略与前面相同。
对于有符号数,测试代码如下:
void main(void){
static INT16 sTemp;
sTemp = 0x0001;
sTemp = sTemp << 1;
sTemp = 0x4000;
sTemp = sTemp << 1;
sTemp = 0x8000;
sTemp = sTemp >> 1;
sTemp = 0x8000;
sTemp = sTemp << 1;
while(1);
}
仿真进行测试:
sTemp = 0x0001;
sTemp = sTemp <<1 ;
执行左移后,sTemp值为0x0002
0000000000000001B ---> 0000000000000010B
可见
有符号数左移,符号位为0,执行左移,舍弃高位,低位补0
sTemp = 0x4000;
sTemp = sTemp << 1;
执行左移后,sTemp值为0x8000
0100000000000000 --> 1000000000000000B
可见策略与前面一致,但需注意,十进制数由16384变为-32768.这和定义的数据类型有关
sTemp = 0x8000;
sTemp = sTemp >> 1;
有符号数,符号位为1,执行右移操作
sTemp值变为0xC000
1000000000000000B --> 1100000000000000B
可见有符号数右移,符号位为1时,执行右移,舍弃低位,高位补1.
sTemp = 0x8000;
sTemp = sTemp << 1;
有符号数,符号位为1,执行左移操作
sTemp变为0x0000
可见有符号数左移,符号位为1时,执行左移,舍弃高位,低位补0
总结
无符号数 | 有符号数 | |||
左移 | 右移 | 左移 | 右移 | |
最高位为0 | 舍弃高位,低位补0 | 舍弃低位,高位补0 | 舍弃高位,低位补0 | 舍弃低位,高位补0 |
最高位为1 | 舍弃低位,高位补1 |
以上结论使用单片机为AT32F403AVCT7,IDE和编译器信息如下:
IDE-Version:
μVision V5.25.2.0
Tool Version Numbers:
Toolchain: MDK-ARM Plus Version: 5.25.2.0
Toolchain Path: D:\Keil_v5\ARM\ARMCC\Bin
C Compiler: Armcc.exe V5.06 update 6 (build 750)
Assembler: Armasm.exe V5.06 update 6 (build 750)
Linker/Locator: ArmLink.exe V5.06 update 6 (build 750)
Library Manager: ArmAr.exe V5.06 update 6 (build 750)
Hex Converter: FromElf.exe V5.06 update 6 (build 750)
CPU DLL: SARMCM3.DLL V5.25.2.0
Dialog DLL: DCM.DLL V1.17.1.0
Target DLL: CMSIS_AGDI.dll V1.29.10.0
Dialog DLL: TCM.DLL V1.35.1.0
其他编译器是否满足此规律,需要另行验证。