深入剖析C函数参数的结合顺序及a++和++a的区别
来源:互联网 发布:csgo全皮肤mac破解版 编辑:程序博客网 时间:2024/06/16 10:49
C语言函数参数的结合顺序
今天上课时老师提出了一个关于C语言的函数参数的结合顺序的问题以及a++和++a有什么区别的问题,为了弄清楚这个问题,我写了如下的代码反汇编进行分析:
#include <stdio.h>#include <stdlib.h>int func(int a, int b, int c, int d);int main(){ int a = 1; int b = 2; func(a++, ++a, ++a, a++); system("pause");}int func(int a, int b, int c, int d){ printf("%d %d %d %d\n", a, b, c, d); return 0;}
在这个程序中,我再调用func的那一行代码设置断点,并且进行反汇编,反汇编后的代码:
由于调用func函数时,传入的参数都是a,因此调用func函数的那一行代码反汇编后都是对a进行操作的代码,不容易判断出各个参数的执行顺序,所以我将调用func时改为传入四个不同的参数,修改代码如下:
重新反汇编:
从上面的汇编代码就很容易看出来了,调用func这个函数时,会依次将d、c、b、a四个参数从内存中取出来,然后压入堆栈中,最后使用call调用func函数,因此可以推断C语言函数参数的执行顺序是从右至左的。
a++及++a的区别
弄清楚了函数参数的执行顺序就可以继续通过反汇编弄清楚a++和++a的区别了。
还是使用最开始的代码:
根据上面参数执行顺序的规则,执行func(a++, ++a, ++a, a++)时参数从右至左执行,于是我进行判断,最右的a++是先使用值再自加,于是传入1,从右至左第二个a这时等于2,因为是前置++,所以判断传入3,从右至左第三个参数同理判断传入4, 从右至左第四个参数因为是后置++,因此判断传入4,最后执行完后a=5,所有我判断传入参数是4 4 3 1,但是执行结果:
为什么会产生这样的结果呢?通过对调用func的这一行代码进行反汇编:
通过参数从右向左执行的原则,可以推断出从右至左的a++、++a、++a、a++对应的汇编代码,从这里我们就看出来了a++和++a的区别:
a++:
++a:
从上面可以看出,++a是将a从内存中取出,存入寄存器,加1后再送回a所在的内存空间中;而a++则是先将a从内存中取出来,再存入ebp寄存器中的内容减去0DC所得值作为内存偏移地址所在的内存空间中,为什么要先将a存入另外的内存空间呢?继续分析参数执行完后的汇编代码:
在程序真正跳转到func之前,还执行了这些代码,这些代码的作用就是将函数的参数压入栈中,最后调用func函数,而func函数中则从栈中取出这些参数,这个过程就是参数传递的过程。在上述代码中,我们看第一个和第四个箭头所指的代码,这刚好对应第一个和第四个参数,它们是从分别从ebp-0DC和ebp-0E0地址所对应的内存中取出值,然后压入栈,而第二和第三个箭头对应的第二个和第三个参数,则是直接从a所在内存区域取出a的值,然后压入栈中。
从这里我们就可以看出a++和++a的区别了,a++会将a的值保存到内存的一个临时区域,或者说存放在一个临时变量中,然后a自加1,取a++的值时就从内存或这个临时变量中取出a的值,这时取出的值是a自加之前的值,最后再使用这个值;而++a则是直接将a的值自加1,使用它的值时也是从a所在内存中直接取出的。
对于结果为什么会是4 5 5 1,通过反汇编也可以很清楚的看出来了,调用func时是先从右至左执行完后才传入参数的,对于++a直接使用最后的a的值,对于a++则使用执行这条语句之前a的值,如示例代码中,执行第一个a++时,a的值为4,因此传入的值就是4,而最后执行完这四条语句后a的值为5,因此中间两个参数传入的值为5,所以最后的结果为4 5 5 1。
- 深入剖析C函数参数的结合顺序及a++和++a的区别
- C语言中参数执行顺序及a++与++a实现的区别
- 深入解析a++和++a的区别
- C语言中值得深入知识点----数组做函数参数、数组名a与&a区别、数组名a的"数据类型"
- a++与++a及a--和--a的区别
- C++: A a() 和 A a 的区别。
- 深入剖析C/C++函数的参数传递机制
- 深入剖析C/C++函数的参数传递
- 深入剖析C/C++函数的参数传递机制
- 深入剖析C/C++函数的参数传递机制
- C++ * a和*&a作为函数的参数时有什么区别
- 深入剖析变长参数函数的实现
- 深入剖析变长参数函数的实现
- a 和&a的区别
- a和&a的区别
- a 和&a 的区别
- a++和++a的区别
- a和&a的区别
- Linux操作系统教学进度计划表
- Java后端工程师学习大纲
- 快速乘 + 快速幂 + 取模
- 2034: [2009国家集训队]最大收益
- java
- 深入剖析C函数参数的结合顺序及a++和++a的区别
- iOS 【自适应拆分换行评论 UILabel 列表-类车主评论页面】
- SlidingMenu最简单的使用,实现侧拉效果
- Camera显示之Hal层的适配
- (一)整合spring cloud云服务架构
- 练习一(轮播+侧滑+TabLayout+PullTorefresh)
- Linux如何查看登陆用户信息
- 高晓松三问阿里巴巴合伙人,为什么来 为什么留 为什么战
- 机器学习0基础学习路线