有趣的++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 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
随机推荐
- POJ 2686 Traveling by Stagecoach
状压DP dp[s][p]用了哪几张票,到哪个节点的最小费用. 注意:G++ %.3lf输出会WA,但C++能过:改成%.3f,C++,G++都能AC #include<cstdio> # ...
- mysql面试
第一方面:30种mysql优化sql语句查询的方法 避免全表扫描: 1.where 及 order by 上建立索引.2.避免在 where 子句中使用!=或<>操作符3. select ...
- P3197 [HNOI2008]越狱
题目描述 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱 输入输出格式 输入 ...
- NYoj1058
水题,dfs,裸的,本来这道题没什么好写的,只是第一次写的代码慢的出奇,纪念一下那个奇怪的思路 链接:http://acm.nyist.net/JudgeOnline/problem.php?pid= ...
- 自适应网页设计/响应式Web设计
zccst转 很早就有人设想,能不能”一次设计,普遍适用”,让同一张网页自动适应不同大小的屏幕,根据屏幕宽度,自动调整布局(layout)? 一.”自适应网页设计”的概念 2010年,Ethan Ma ...
- IOS FMDB模糊查询
http://blog.sina.com.cn/s/blog_9630f1310101fx1d.html /查询记录 -(NSArray*)selectitemDream_desc:(JiemengS ...
- ucos任务优先级从64到256,任务就绪表的改变
Ucos在任务调度中经常使用的技术为任务就绪表,在之前的文章中使用的例子是低于64个优先级的任务就绪表查找方法,现在ucos将任务扩展到256优先级之后,任务就绪表的查找也做了一定的修改,今天来讲讲 ...
- iOS 获取本地文件的各种坑
1.无论:TXT,EPUB,PDF等各种格式的文件,保存到本地的时候,最好都保存成字母或者数字,不要保存成汉字,否则,在取文件的时候,由于编码的问题,各种瓦特 2.如果文件名真的保存成了汉字,那么进行 ...
- VMWare虚拟机bridged、host-only和NAT网络模式的区别和用法
VMWare提供了三种工作模式,它们是bridged(bridged 模式).NAT( 网络地址转换模式)和host-only(主机模式) . 1 VMWare虚拟机bridged.host-onl ...
- Maven deploy时报Fatal error compiling: tools.jar not found错误的问题处理
摘自:http://blog.csdn.net/achilles12345/article/details/19046061 在Eclipse环境下,使用Maven进行deploy时发现报了该错误:F ...