物联网学习:算术移位和逻辑移位实现分析
算术移位和逻辑移位实现分析
先来看下面这道题:
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将改变符号位,所以只能采用算术右移。
总结:只有有符号数右移才采用算术右移,否则其它情况都采用逻辑移位操作(逻辑左移或逻辑右移)。原来只要明白计算机是以补码方式保存数值的,就一切都清楚了。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
阿里云物联网平台设备影子功能演示
概述 物联网平台提供设备影子功能,用于缓存设备状态。设备在线时,可以直接获取云端指令;设备离线时,上线后可以主动拉取云端指令。设备影子是一个 JSON 文档,用于存储设备上报状态、应用程序期望状态信息。每个设备有且只有一个设备影子,设备可以通过MQTT获取和设置设备影子来同步状态,该同步可以是影子同步给设备,也可以是设备同步给影子。本文使用MQTT.fx工具快速测试设备影子的相关功能。 实验测试 设备影子Topic 物联网平台已为每个设备预定义了两个Topic,用于实现数据流转,可以直接使用。 /shadow/update/${YourProductKey}/${YourDeviceName}设备和应用程序发布消息到此Topic。物联网平台收到该Topic的消息后,将消息中的状态更新到设备影子中。 /shadow/get/${YourProd
- 下一篇
物联网:关于Nand flash读写范围的问题
物联网:Nand flash读写范围的问题 很多时候对nand的操作都是通过主控的nand控制器直接完成,或者更多时候是通过MTD标准操作接口完成读写擦的过程,然而有些细节问题有必要在这里讨论一下,我分为以下几点进行说明: 1、擦除过程:擦除过程是将0变成1的过程,即充电的过程(比如SLC中,当低于某个电压值表示0,高于这个电压值则表示1;而对于MLC来说可以有多个阈值,所以可以保存更多bit)。擦除过程是按块进行的,但启始地址是页地址,不过擦除过程在内部是有边界对齐的,也就是说当擦除启始地址不是块对齐时,只能擦除本块,而不能垮越到第二个块继续擦除,也就是无论我们给的地址是否页对齐,本块都将擦除,不会有任何保留。 需要注意的是:块擦除时每一页的oob区也同时被擦除掉了,所以一般擦除前先读取块的第一页的两个字节看是否为0xff(512Byte页大小nand的坏块信息放在第6个字节中,ECC占用0、1、2、3、6、7字节;2k页大小的nand有24位ECC放在oob区的40-63字节处),不是的话就不要擦除,0xff表示正常,其它值表示错误,否则将会擦掉所有坏块信息,尤其是出厂时写入的。 ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS关闭SELinux安全模块
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7设置SWAP分区,小内存服务器的救世主