有趣的++i和i++
作为一个天天和代码“约会”的人来说i++和++i这玩意再熟悉不过了,因为使用频率太高了。
虽然如此,但也未必见得我们真的了解她,不妨猜猜下面的输出结果。
#inlcude <stdio.h> int main(void)
{
int i = , j = ; printf("i[1] = %d i[2] = %d\n", i++ + ++i, ++i + i++); printf("j[1] = %d j[2] = %d\n", j++ + j++, ++j + ++j); return ;
}
最后结果是:
i[1] = 6 i[2] = 2
j[1] = 4 j[2] = 4
想要得出正确答案,仅仅知道前+和后+的区别是不够的,这里面有两个坑。
第一个是cpu处理前+和后+真正的执行过程。
第二个是printf这个“小妾”暗藏一腿。
先把简单的第二个坑填了,以一般的思维和习惯会下意识的认为printf先计算前面那个表达式(即代码中的i[1] 和 j[1]),然后计算后面那个表达式的值(即 代码中的i[2]和j[2]),事实却正好相反,要先算后面再算前面。
要想填平第一个大坑,我们需要研究编译后的汇编代码。
@by tid_think
@arm-linux-gcc -S test.c -o test.s
@tiny4412
.cpu arm1176jzf-s
.eabi_attribute ,
.fpu vfp
.eabi_attribute ,
.eabi_attribute ,
.eabi_attribute ,
.eabi_attribute ,
.eabi_attribute ,
.eabi_attribute ,
.eabi_attribute ,
.eabi_attribute ,
.file "test.c"
.section .rodata
.align
.LC0:
.ascii "i[1] = %d i[2] = %d\012\000"
.align
.LC1:
.ascii "j[1] = %d j[2] = %d\012\000"
.text
.align
.global main
.type main, %function
main:
@ args = , pretend = , frame =
@ frame_needed = , uses_anonymous_args = @by tid_think
@关键代码
stmfd sp!, {fp, lr} @将fp,lr两个寄存器的值压栈
add fp, sp, # @fp = sp +
sub sp, sp, # @sp = sp +
mov r3, # @r3 =
str r3, [fp, #-] @将r3的值()写入 fp - 的地方 int i = 0
mov r3, # @r3 =
str r3, [fp, #-] @将r3的值()写入 fp - 的地方 int j = 0
ldr r1, .L2 @将.L2的地址加载到r1
ldr r3, [fp, #-] @将fp -8地址上的值(i = ) 给r3
add r3, r3, # @r3 = r3 + ===>i =
str r3, [fp, #-] @将r3的值()写入 fp - 的地方 i
ldr r2, [fp, #-] @将fp -8地址上的值(i = ) 给r2
ldr r3, [fp, #-] @将fp -8地址上的值(i = ) 给r3
add r2, r2, r3 @r2 = r2 + r =
ldr r3, [fp, #-] @将fp -8地址上的值(i = ) 给r3
add r3, r3, # @ r3 = r3 + =
str r3, [fp, #-] @将r3的值()写入 fp - 的地方 i
ldr r3, [fp, #-] @将fp -8地址上的值(i = ) 给r3
add r3, r3, # @ r3 = r3 + =
str r3, [fp, #-] @将r3的值()写入 fp - 的地方 i
ldr r0, [fp, #-] @将fp -8地址上的值(i = ) 给r0
ldr r3, [fp, #-] @将fp -8地址上的值(i = ) 给r3
add r3, r0, r3 @ r3 = r0 + r3 =
ldr r0, [fp, #-] @将fp -8地址上的值(i = ) 给r0
add r0, r0, # @r0 = r0 + =
str r0, [fp, #-] @将r0的值()写入 fp - 的地方
mov r0, r1 @r0 = r1 给printf传参数1
mov r1, r2 @r1 = r2 = 给printf传参数2
mov r2, r3 @r2 = r3 = 给printf传参数3
bl printf @调用printf打印
ldr r1, .L2+4 @开始计算j了............
ldr r2, [fp, #-]
ldr r3, [fp, #-]
add r2, r2, r3
ldr r3, [fp, #-]
add r3, r3, #
str r3, [fp, #-]
ldr r3, [fp, #-]
add r3, r3, #
str r3, [fp, #-]
ldr r3, [fp, #-]
add r3, r3, #
str r3, [fp, #-]
ldr r3, [fp, #-]
add r3, r3, #
str r3, [fp, #-]
ldr r0, [fp, #-]
ldr r3, [fp, #-]
add r3, r0, r3
mov r0, r1
mov r1, r2
mov r2, r3
bl printf
mov r3, #
mov r0, r3
sub sp, fp, #
ldmfd sp!, {fp, pc}
.L3:
.align
.L2:
.word .LC0
.word .LC1
.size main, .-main
.ident "GCC: (ctng-1.8.1-FA) 4.5.1"
.section .note.GNU-stack,"",%progbits
汇编代码解析:
首先刨去没用的信息,直接从 31行开始看
33~35行都是对栈指针的一些偏移和保存。
从以上汇编代码看可以看出简单的两句C编译成汇编就是一大坨,如果用纯汇编写15行左右应该就能搞定 执行效率几乎是C的20倍……………………
有趣的++i和i++的更多相关文章
- 谈谈一些有趣的CSS题目(十二)-- 你该知道的字体 font-family
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
- 谈谈一些有趣的CSS题目(十一)-- reset.css 知多少?
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
- 几个有趣的WEB设备API(二)
浏览器和设备之间还有很多有趣的接口, 1.屏幕朝向接口 浏览器有两种方法来监听屏幕朝向,看是横屏还是竖屏. (1)使用css媒体查询的方法 /* 竖屏 */ @media screen and (or ...
- 谈谈一些有趣的CSS题目(三)-- 层叠顺序与堆栈上下文知多少
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 谈谈一些有趣的CSS题目(一)-- 左边竖条的实现方法
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 谈谈一些有趣的CSS题目(二)-- 从条纹边框的实现谈盒子模型
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 谈谈一些有趣的CSS题目(四)-- 从倒影说起,谈谈 CSS 继承 inherit
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 谈谈一些有趣的CSS题目(五)-- 单行居中,两行居左,超过两行省略
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 谈谈一些有趣的CSS题目(六)-- 全兼容的多列均匀布局问题
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
- 谈谈一些有趣的CSS题目(七)-- 消失的边界线问题
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
随机推荐
- 第一次在手机上跑动ane
记录一下: 打包的时候先出现 error 100: descriptor cannot be parsed, 原因是命名空间少了个引号,自己粗心所致 第二次打包出现了invalid namespace ...
- 将Web项目访问的URL项目名设置为"/"
工具:Eclipse 步骤: 1.鼠标右键项目名--->properties--->Web Project Setting--->Context root. 将Context roo ...
- SecureCRT上传bash: rz: command not found
SecureCRT上传bash: rz: command not found -bash: rz: command not found rz命令没找到? 执行sz,同样也没找到. 安装lrzs ...
- mysql迁移-----拷贝mysql目录/load data/mysqldump/into outfile
摘要:本文简单介绍了mysql的三种备份,并解答了有一些实际备份中会遇到的问题.备份恢复有三种(除了用从库做备份之外), 直接拷贝文件,load data 和 mysqldump命令.少量数据使用my ...
- Grunt 入门
转自:http://user.qzone.qq.com/174629171/blog/1404433906 Grunt被定义为:the javascript task runner. 什么算是Java ...
- Git for Windows 工具下载及配置
前言,关于git工具的帖子:http://cn.v2ex.com/t/225027 最终选择了git for windows这个工具,路径为:https://git-for-windows.githu ...
- POJ 2609 Ferry Loading
双塔DP+输出路径. 由于内存限制,DP只能开滚动数组来记录. 我的写法比较渣,但是POJ能AC,但是ZOJ依旧MLE,更加奇怪的是Uva上无论怎么改都是WA,其他人POJ过的交到Uva也是WA. # ...
- cocos2dx3.5 HTC One X 某些UI白屏或使用ClippingNode造成部分手机白屏
public Cocos2dxGLSurfaceView onCreateView() { Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSu ...
- Zookeeper的基本概念
Reference: http://mp.weixin.qq.com/s?src=3×tamp=1477979201&ver=1&signature=bBZqNrN ...
- HTML 表单元素之 input 元素
介绍HTML 5: 表单元素之 input 元素 表单元素之 input 元素 - text, password, url, telephone, email, search, file, radio ...