C函数中的形式参数可以是基本类型变量名,构造类型变量名和指针类型变量名。对于不同的形式参数,其传递参数的方式不同,总体来说分成两种:按值传递和按地址传递。 当形参是基本类型变量名时,采用按值传递方式;当形参是指针类型变量名或者构造类型变量名时,采用按地址传递方式。 下面通过两个相似的程序说明二者的区别:
//程序一:按地址传递参数
#include <stdio.h>
swap(int *x,int *y){
    int t=*x; *x=*y; *y=t;
}
main(){
    int a=15,b=22;
    printf(“a=%d\tb=%d\n”,a,b);
    swap(&a,&b);
    printf(“a=%d\tb=%d\n”,a,b);
} 
/*//输出结果:
a=15    b=22
a=22    b=15
//程序二:按值传递参数
#include <stdio.h>
swap(int x,int y){
    int t=x; x=y; y=t;
}
main(){
    int a=15,b=22;
    printf(“a=%d\tb=%d\n”,a,b);
    swap(a,b);
    printf(“a=%d\tb=%d\n”,a,b);
} 
//输出结果:
a=15    b=22
a=15    b=22
可以看出,程序一实现了a和b的值的交换,而程序二并没有实现。 先看一下两个程序的栈帧内容有何差别: [](http://www.wjgbaby.com/wp-content/uploads/2018/06/18060901.png)) 
                
//程序一汇编代码片段:
main:
    leal    -8(%ebp), %eax    //将ebp-8里面的内容作为地址放到eax中
    mov1    %eax, 4(%esp)    //作为参数传到esp+4的位置
    leal    -4(%ebp), %eax    //ebp-4传给eax,a=15
    mov1    %eax, (%esp)
    call    swap
    ret
swap:
//以下是准备阶段
    push1    %ebp
    mov1    %esp, %ebp
    push1    %ebx            //ebx是被调用者保存
//以下是过程体
    mov1    8(%ebp), %edx    //R[ecx]<-M[&a]=15
    mov1    (%edx), %ecx    //把15送到了ecx中
    mov1    12(%ebp), %eax    //R[ebx]<-M[&b]=22
    mov1    (%eax), %ebx    //把22送到ebx中
    mov1    %ebx, (%edx)    //ebx中的22替换掉a=15,之后a=22
    mov1    %ecx, (%eax)    //ecx中的15替换掉b=22,之后b=15
//以下是结束阶段
    pop1    %ebx
    pop1    %ebp
    ret
//程序二汇编代码片段:
main:
    leal    -8(%ebp), %eax
    mov1    %eax, 4(%esp)
    leal    -4(%ebp), %eax
    mov1    %eax, (%esp)
    call    swap
    ret
swap:
//以下是准备阶段
    push1    %ebp
    mov1    %esp, %ebp
//以下是过程体
    mov1    8(%ebp), %edx
    mov1    12(%ebp), %eax
    mov1    (%eax), 8(%ebp)
    mov1    %edx, 12(%ebp)
//以下是结束阶段
    pop1    %ebp
    ret
对比图: [](http://www.wjgbaby.com/wp-content/uploads/2018/06/18060904.png) 在给swap过程传递参数时,程序一用了leal指令,而程序二用的是movl指令。因此程序一传递的是a和b的地址,而程序二传递的是a和b的内容。 程序一的swap过程比程序二的swap过程多了三条指令。而且,由于程序一的swap过程更复杂,使用了较多的寄存器,除了三个调用者保存寄存器外,还使用了被调用者保存寄存器EBX,它的值必须在准备阶段被保存到栈中,而在结束阶段从栈中恢复。因而它比程序二又多了一条push指令和一条pop指令。 再来看一下执行swap过程后的main的栈帧中的状态: [](http://www.wjgbaby.com/wp-content/uploads/2018/06/18060902.png)