在函数调用这会涉及到形参与实参个两个概念,于是上网查了一下实参与形参的概念。
实参是指在函数调用时,必须有确切的值以便赋给形参的一种参数,它可以为常量,变量,表达式,函数等。
形参是在定义函数名和函数体时使用的一种参数,目的是用于接收调用该函数时传递的参数。它只能是变量。
1,传值调用,顾名思义,就是对值的传递。但它只是对形参里的值发生了变化,并没有对实参的值有任何变化。接下来我用堆栈法来试试解释, 定义一个函数名为exchange的函数,其作用是实现里面的数交换。代码如下:
#include<stdio.h>
void exchange(int one,int another);
void exchange(int one,int another) {
int temp;
temp=one;
one=another;
another=temp;
}
void main(void){
int num1,num2;
exchange(14,7);
printf("%d %d\n",num1,num2);
}
在主函数定义了两个实参为num1,num2在子函数中定义形参为one,another这种操作等效于one=num1,another=num2。即实参表达式的值在系统堆栈中占用的空间就是与之对应的形参变量的空间。实参先入栈,栈顶指针esp往上飘,即num2先入栈,占据4个字节,接着num1入栈,等效于站在num2上,再占据4个字节,在函数调用时栈底指针ebp移到当前栈顶指针位置,再接着temp入栈,等效于把当前 栈底指针向上的空间分配给了子函数的局部变量即。。。。。。。。。temp,再占据4个字节,函数调用完后恢复到子函数调用之前的栈顶和栈底指针.
进行temp=one时,等效于把one空间的值赋给temp的空间,即temp为14,
one=another ,等效于把another空间的值赋给one空间, 即one为7,
another=temp等效于把temp空间的值赋给another空间,即another为14。
此刻one和another空间的值分别为7,14但num1和num2空间的值根本就没变。故不能实现交换。
2,引用调用
同样的例子用到这个函数中
void realexchange(int *one,int *another){
int temp;
temp=*one;
*one=*another;
*another=temp;
}
void main(void){
int num1,num2;
realexchange(14,7);
printf("%d %d\n",num1,num2);
}
在主函数定义为这两个实参的取地址即&num1,&num2。这种操作等效于one指向num1,anothor指向num2。如图
在进行temp=*one时,等效于将one所指空间的值赋给temp的空间,即temp为14; *one=*another等效于将another所指向的空间的值赋给one所指向的空间,即num1为7;*another=temp等效于把temp空间的值赋给another所指向的空间,即num2为14。这样下来num1与num2的值发生了变化。即转换成功。
总而言之,事实上,形参的空间就是实参表达式的值入栈的空间,它并没有额外的申请空间。若在以后形参表达式的值能够影响到实参的结果时,则实参应该传地址给形参,若不需要形参的表达式来改变实参的值时,则只需要传值给形参即可。。。