文章目录

C语言函数参数的结合顺序及a++和++a的区别

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 %dn", 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。

本文转载自csdn博客主“宋铮”。

本文网址:http://www.santii.com/article/88.html

您可能还会对这些C文章感兴趣


数据更新时间:2018-09-22