小小千想和您聊一聊

当前位置: 首页> 技术分享> 算术移位和逻辑移位实现分析

算术移位和逻辑移位实现分析

  先来看下面这道题:

unsigned int i = 8;
int main()
{
i = i<<3;//输出结果i = 64
}

  上面的变量i是采用逻辑移位还是算术移位呢?

  逻辑移位,简单理解就是物理上按位进行的左右移动,两头用0进行补充,不关心数值的符号问题

  算术移位,同样也是物理上按位进行的左右移动,两头用0进行补充,但必须确保符号位不改变

  但我们好奇的是“i<<3”和“i>>3”到底采用的是算术还是逻辑移位呢?其实单从C语言本身来看可能没有太多突破,因为C最终会被编译器编译成目标平台的汇编代码,所以必须要结合编译器和汇编程序来分析以上代码,下面主要从反汇编入手分析,对ARM平台下有关移位的指令有:

  LSL(逻辑左移)

  LSR(逻辑右移)

  ROR(循环右移)

  ASL(算术左移)

  ASR(算术右移)

  RRX(带扩展的循环右移)

  下面我们来看看上面那段C程序的反汇编结果:

  算术移位和逻辑移位实现分析

  结论:说明无符号数采用的是逻辑左移。

  那么经过测试我们发现以下几份代码反汇编结果和上面的情况是一样的,都是逻辑左移:

  再来看一下:

signed int i = 8;
int main()
{
i = i<<3;//输出结果i = 64
}
signed int i = -8;
int main()
{
i = i<<3;//输出结果i = -64
}

  结论:说明不管是否有无符号类型,也不管值的正负,均采用的是逻辑左移。

  接下来看看右移:

unsigned int i = 8;
int main()
{
i = i>>3;//输出结果i = 1
}

  反汇编结果:

  结论:说明无符号数采用的是逻辑右移。

  再看看有符号数的右移操作:

signed int i = 8;
int main()
{
i = i>>3;//输出结果i = 1
}

  反汇编结果:

  算术移位和逻辑移位实现分析

  结论:说明有符号数采用的是算术右移。

  经过测试发现以下代码反汇编结果和上面的情况也是一样的:

signed int i = -8;
int main()
{
i = i>>3;//输出结果i = -1
}

  结论:说明只要是有符号数,不管值是正还是负,右移时采用的都是算术右移。

  疑问:按照移位补0的原则,为何左移都是逻辑移位呢?

  答疑:先看看“-8”和“8”在计算机内存中的值分别是:

  0xfffffff8

  0x8

  由于计算机均按补码保存数值,所以不管符号正负,左移对于符号位并不产生影响,而右移则就不同了,无符号数怎么右移都不影响符号位,但是有符号数逻辑右移时高位补0将改变符号位,所以只能采用算术右移。

  总结:只有有符号数右移才采用算术右移,否则其它情况都采用逻辑移位操作(逻辑左移或逻辑右移)。原来只要明白计算机是以补码方式保存数值的,就一切都清楚了。

上一篇:PWM死区(Dead Zone)的作用和意义

下一篇:创建数据库和数据表

QQ技术交流群

千锋物联网官方①群
858310440

加入群聊

用户登录

手机号:

密码:

图形验证码:

点击切换

用户注册

手机号:

登录密码:

图形验证码:

点击切换

短信验证码:

获取验证码

忘记密码

1安全验证

2重置密码

手机号:

图形验证码:

短信验证码:

获取验证码

忘记密码

1安全验证

2重置密码

新密码:

确认新密码:

获取课程

添加小千老师微信,获取课程信息

如何获取课程?

一、需拥有此本教材

如没有,可点击下方入口购买当当购买入口京东购买入口

二、添加小千老师,发送拥有凭证,解锁课程资源

1.购买该教材的订单信息
2.拥有的实体书信息等

更换手机号

新手机号:

图形验证码:

短信验证码:

获取验证码