作为一个天天和代码“约会”的人来说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++的更多相关文章

  1. 谈谈一些有趣的CSS题目(十二)-- 你该知道的字体 font-family

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  2. 谈谈一些有趣的CSS题目(十一)-- reset.css 知多少?

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  3. 几个有趣的WEB设备API(二)

    浏览器和设备之间还有很多有趣的接口, 1.屏幕朝向接口 浏览器有两种方法来监听屏幕朝向,看是横屏还是竖屏. (1)使用css媒体查询的方法 /* 竖屏 */ @media screen and (or ...

  4. 谈谈一些有趣的CSS题目(三)-- 层叠顺序与堆栈上下文知多少

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  5. 谈谈一些有趣的CSS题目(一)-- 左边竖条的实现方法

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  6. 谈谈一些有趣的CSS题目(二)-- 从条纹边框的实现谈盒子模型

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  7. 谈谈一些有趣的CSS题目(四)-- 从倒影说起,谈谈 CSS 继承 inherit

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  8. 谈谈一些有趣的CSS题目(五)-- 单行居中,两行居左,超过两行省略

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  9. 谈谈一些有趣的CSS题目(六)-- 全兼容的多列均匀布局问题

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  10. 谈谈一些有趣的CSS题目(七)-- 消失的边界线问题

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

随机推荐

  1. 第一次在手机上跑动ane

    记录一下: 打包的时候先出现 error 100: descriptor cannot be parsed, 原因是命名空间少了个引号,自己粗心所致 第二次打包出现了invalid namespace ...

  2. 将Web项目访问的URL项目名设置为"/"

    工具:Eclipse 步骤: 1.鼠标右键项目名--->properties--->Web Project Setting--->Context root. 将Context roo ...

  3. SecureCRT上传bash: rz: command not found

    SecureCRT上传bash: rz: command not found -bash: rz: command not found rz命令没找到? 执行sz,同样也没找到.     安装lrzs ...

  4. mysql迁移-----拷贝mysql目录/load data/mysqldump/into outfile

    摘要:本文简单介绍了mysql的三种备份,并解答了有一些实际备份中会遇到的问题.备份恢复有三种(除了用从库做备份之外), 直接拷贝文件,load data 和 mysqldump命令.少量数据使用my ...

  5. Grunt 入门

    转自:http://user.qzone.qq.com/174629171/blog/1404433906 Grunt被定义为:the javascript task runner. 什么算是Java ...

  6. Git for Windows 工具下载及配置

    前言,关于git工具的帖子:http://cn.v2ex.com/t/225027 最终选择了git for windows这个工具,路径为:https://git-for-windows.githu ...

  7. POJ 2609 Ferry Loading

    双塔DP+输出路径. 由于内存限制,DP只能开滚动数组来记录. 我的写法比较渣,但是POJ能AC,但是ZOJ依旧MLE,更加奇怪的是Uva上无论怎么改都是WA,其他人POJ过的交到Uva也是WA. # ...

  8. cocos2dx3.5 HTC One X 某些UI白屏或使用ClippingNode造成部分手机白屏

    public Cocos2dxGLSurfaceView onCreateView() { Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSu ...

  9. Zookeeper的基本概念

    Reference:  http://mp.weixin.qq.com/s?src=3&timestamp=1477979201&ver=1&signature=bBZqNrN ...

  10. HTML 表单元素之 input 元素

    介绍HTML 5: 表单元素之 input 元素 表单元素之 input 元素 - text, password, url, telephone, email, search, file, radio ...