这里主要用“交换两个数”的例子作叙述:
话不多说,先上个新手都容易犯的错误:
#include<stdio.h>
void exchange(int,int);
void exchange(int one,int another)
{
int tmp;
tmp = one;
one = another;
another = tmp;
}
int main()
{
int num1;
int num2;
exchange(num1,num2);
printf("交换后的数值:%d%d",num1,num2);
return 0;
}
上述做法,似乎是对主函数的值进行交换,但实则并没有达到理想效果。先说一种作者的形象理解,主函数中定义了两个变量,这两个变量呢,实际上是申请了两段连续的存储空间,将num1及num2的值分别存储,那么要交换它们的值,要怎么做呢,可以这么想,有两台电脑,分别在两个位置,这时,两台电脑其实就是两个值,而它们的两个位置,其实就是他们的地址。这时要交换他们,肯定是你告诉我他们分别的位置,即地址,我去交换,也就是说要传出它们的地址。参数既然是地址,那肯定是int * 。所以上述的做法显然不能完成操作,即需要这样做:
#include<stdio.h>
realexchange(int *num1,int *num2);
void realexchange(int *one ,int *another)
{
int tmp;
tmp = *one;
*one = *another;
*another = tmp;
}
int main()
{
int num1;
int num2;
scanf("%d%d",&num1,&num2);
realexchange(&num1,&num2);
printf("交换后的值:%d %d",num1,num2);
return 0;
}
当然这只是一种形象理解,其实内部运行是这样的。程序需要调入内存,方能执行。调入内存的哪里呢,实际上是调入内存的堆栈区,当程序运行时,主函数先运行,这时对定义的num1和num2申请空间,也就是入栈。接下来执行realexchenge(&num1,&num2)操作,这是注意了,内部执行过程是这样的。
首先将&num2入栈,再将&num1入栈,这里的入栈所占用的空间与num2和num1明显为两段空间。而接下来调用子函数时,形参变量的空间直接占用实参变量的空间。也就是one == &num1,同理another,这时利用两个变量的地址,便可以完成对两个变量的值交换操作。这样便达到了值传递的目的。子函数执行完毕后,继续执行主函数,而为子函数分配的空间被立即释放。
之前的exchenge()函数,之所以迷惑人,是以为错误的将为主函数变量分配的空间与函数调用时入栈的空间理解为一段空间。其实实参表达式入栈的空间就是形参变量的空间,而非主函数变量的空间。