作为一个天天和代码“约会”的人来说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. mybatis+spring事务

    http://www.mybatis.org/spring/zh/transactions.html 第四章 事务 一个使用 MyBatis-Spring 的主要原因是它允许 MyBatis 参与到 ...

  2. ISP和IAP

    ISP(在系统编程)是一种不依赖于单片机自身软件的程序下载方式,特点是不需要从电路板上取下单片机,通过某种方式使单片机进入ISP模式,开放编程接口,由其使用的计算机将新的程序代码写入到存储器内.我们平 ...

  3. CodeForces 622C Not Equal on a Segment

    预处理p[i],p[i]表示:[p[i],i]这段闭区间上所有数字都是a[i] 询问的时候,如果xi==a[ri]并且p[ri]<=li,一定无解 剩下的情况都是有解的,如果xi!=a[ri], ...

  4. HDU 5620 KK's Steel

    想了一下发现是斐波那契数列.....水题 #include <stdio.h> #include <algorithm> #include <string.h> # ...

  5. N-gram语言模型简单介绍

    N-gram语言模型 考虑一个语音识别系统,假设用户说了这么一句话:"I have a gun",因为发音的相似,该语音识别系统发现如下几句话都是可能的候选:1.I have a ...

  6. 对AD域进行定期自动备份设置图解

    今天为大家讲解一下,如何对域进行定期的备份,因为如果域出问题了,在公司里那可就不好玩了啊,对做定期备份,在域出问题的时候可以及时恢复,减少对域重建而浪费大量的时间,同样也耽误公司员工的工作,这样的事情 ...

  7. model first,DB first,code first

    code first迁移数据库1.打开程序包管理器控制台2.运行Enable-Migrations,运行之后会生成Migrations文件夹与相应的文件 Configuration.cs3.设置 Au ...

  8. pip安装icu失败:Command "python setup.py egg_info" failed with error code 1 in

    问题 Mac 下通过 pip 安装 icu 失败. 解决办法及原因 问题的原因是因为icu库中的某一行代码找不到一个文件,获取不到ICU_VERSION的值. # Install icu brew i ...

  9. 设置ubuntu下使用ls命令显示文件颜色显示

    文件颜色属性: # Attribute codes: 字符属性# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed#00无 ...

  10. java细节,细的你想象不到

    一. 构造方法每次都是构造出新的对象,不存在多个线程同时读写同一对象中的属性的问题,所以不需要同步 . 如果父类中的某个方法使用了 synchronized关键字,而子类中也覆盖了这个方法,默认情况下 ...