2、第二题揭秘
先来看一下打印结果吧:
Java 运行结果:
C/C++ 运行结果:
可以清晰地看到 Java 的打印结果与 C/C++ 不同,在下面将做出我的解释。
2.1、Java 中的printf 是格式化输出
诸如 %d、%f、%s 分别代表着整型、浮点型、字符串类型的占位符,在进行打印的时候会被后续的变量替代。在 a 为 2 时, a++ 的结果为 2 ,自增后 a 变为 3,然后进行 ++a,结果为 4,而 Java 的打印结果也确实如此。
按照同样的理解,为什么 C/C++ 中的结果是 3 4 呢?这就涉及到了 函数调用约定 问题,printf 和 cout 参数是右向左进行入栈操作的。那到底这个入栈操作是怎么进行的呢,那就往下看看汇编的指令吧!
2.2、C/C++ 打印时按照从右向左顺序入栈
汇编层面解析 printf 函数执行顺序:
由上面汇编指令得知执行流程为:
1.先处理最后一个参数 ++a:
通过 mov 传送指令将 内存中a对应的值传送到累加器 eax 中
累加器进行加 1 操作后将此值再次送回内存
2.然后处理参数 a++:
先将此时 a对应的值传送到寄存器 ecx 中,然后存储到另一个内存单元中,为了方便描述,将该内存单元称为 temp
mov 指令不允许两边的操作数同时为内存,因此使用 ecx 作为媒介
随后将 a 对应的值送到寄存器 edx 中并进行加 1 操作并重新送入原内存中
3.完后,将 a 对应的值传送到 eax 中通过 push 指令入栈,将 temp 内存对应的值送到 ecx 中也通过 push 入栈,最后将剩余字符串入栈,调用函数,完成打印。
结果分析:
a++ 的结果就是临时存储单元 temp 对应的结果,而此结果正是 3,++a 的结果就是累加器 eax 存储的值,该值经过两次 add 1 操作,从 2 变为了 4,最终结果也就是 4。这也正是C 语言printf 输出的结果。
3、 留一道课后作业
对于C++中的 cout 执行流程我便不做解释,过程与 printf 一致,都是右向左先进行入栈操作,看了这么多,来一个练习题吧:
最终打印结果为?我做个投票吧,一天后我在评论区公布答案,大家快来检验一波学习成果!