博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux gcc for 循环中 i=i++ 会造成死循环问题及 ++i / i++ 汇编分析
阅读量:5860 次
发布时间:2019-06-19

本文共 1245 字,大约阅读时间需要 4 分钟。

hot3.png

在把 Windows 程序移植到 Linux 时遇到了死循环,最后定位到了类似这种的语句 for (i = 0; i < 1; i = i++),

别问我是谁写的,为什么这么写(泪目)。

根据我自己的感觉, i = i++ 应该等价于 i++(C标准中 i=i++ 的行为未定义), Windows 上确实是这样,但 Linux 不是,这应该是编译器差异造成的。

--------------------------------------- 可 i 的分割线 No.0 --------------------------------------------------------------

那么问题来了,为什么会这样呢?

用 arm-linux-gcc  -S  i.c 汇编一下,编译结果和源码如下(gcc 汇编的代码不太好看,所以用了 arm 版的):

首先介绍一下出现的汇编指令:

mov r3, #0       (把常数值赋值给 r3,相当于 r3=0)

str r3, [fp, #-8] (把 r3 的值存储到内存地址 [fp, #-8])

ldr r3, [fp, #-8] (把内存地址 [fp, #-8] 的值载入到 r3,和 str 相反)

add r2, r3, #1    (r2 = r3 + 1)

okey, 其实是先把 i 的原始值缓存到 r3,然后加1的值赋给 r2,r2会更新 i 值(因为 i++), 最后 r3 也会更新 i 值(因为 i=),至于为何是这个顺序,请呼叫大神吧。所以,i 的值会一直为0,导致文章开头的 for 循环就死了。

--------------------------------------- 可 i 的分割线 No.1 --------------------------------------------------------------

为了好理解,我还汇编出了 j=i++,如下:

j = i++ : 还是先缓存 i 的原始值,然后把加1的 i 值赋给 i,最后在把缓存的 i 的原始值赋给 j(和 i = i++ 的顺序一样)。

j = ++i : 先更把加1的 i 值赋给 i,然后再取出 i 值赋给 j 。

--------------------------------------- 可 i 的分割线 No.2 --------------------------------------------------------------

此外,一直想看看i++ 和++i 的汇编有什么不同,结果如下:

因为一直都听过这个说法,for 循环中 ++i 的效率比 i++ 高,但从上图中可以看成,在单独的语句中,

++i 和 i++ 是一样的(gcc 系列编译器),不过还是推荐用 ++i,为了移植性,不能相信编译器。

转载于:https://my.oschina.net/u/1416148/blog/362516

你可能感兴趣的文章
大数据核心知识点:Hbase、Spark、Hive、MapReduce概念理解,特点及机制
查看>>
SQLServer之数据类型解析
查看>>
PHP实现并发请求
查看>>
css自定义属性和聚光灯效果
查看>>
Java知识点总结(反射-反射机制性能问题)
查看>>
命令行笔记
查看>>
5种方法教你用Python玩转histogram直方图
查看>>
HTML_关于现代前端必要知识
查看>>
使用 Laravel 制定 MySQL 数据库备份计划任务
查看>>
什么是模块,什么是组件
查看>>
前端跨域策略实践----cors,jsonp
查看>>
Yii2:教你一步步写一个微信商城(一)
查看>>
第3章:抽象数据类型(ADT)和面向对象编程(OOP) 3.5 ADT和OOP中的等价性
查看>>
备忘录模式(Memento)
查看>>
【跃迁之路】【490天】刻意练习系列249(2018.06.10)
查看>>
js中的数据类型和数据类型转换
查看>>
基于阿里云HiTSDB搭建工业物联网平台实践
查看>>
【跃迁之路】【439天】程序员高效学习方法论探索系列(实验阶段196-2018.04.20)...
查看>>
基于Yii2的应用开发引擎RageFrame
查看>>
树莓派入门指北 | 树莓派小无相系列
查看>>