1. 探究实参与形参它们相互独立
还记得在函数那一节中讨论过的代码吗?
#include <stdio.h>
void swap(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
int main()
{
int a, b;
int temp;
a = 1;
b = 2;
printf("a=%d b=%d\n", a, b);
// 交换a,b变量
swap(a, b);
printf("a=%d b=%d\n", a, b);
return 0;
}
由于主调函数的变量a,b与被调函数的形参x,y它们相互独立。函数swap
可以修改变量x,y,但是却无法影响到主调函数中的a,b。
现在利用取地址运算符,分别打印它们的首地址,让我们从内存的角度,来分析一下它们。
#include <stdio.h>
void swap(int x, int y)
{
// 打印x,y的首地址
printf("&x= %u\n", &x);
printf("&y= %u\n", &y);
int temp = x;
x = y;
y = temp;
}
int main()
{
int a, b;
int temp;
a = 1;
b = 2;
// 打印a,b的首地址
printf("&a= %u\n", &a);
printf("&b= %u\n", &b);
// 交换a,b变量
swap(a, b);
return 0;
}
a在内存中为首地址10484860开始的sizeof(int)
字节。
b在内存中为首地址10484856开始的sizeof(int)
字节。
x在内存中为首地址10484832开始的sizeof(int)
字节。
y在内存中为首地址10484836开始的sizeof(int)
字节。
调用swap
函数时,a的值1,传给x。b的值2,传给y。
图中,红色数值为数据对象首地址,黑框内的为变量名和值。 即使x,y已经交换了,但是并未影响a,b。
2. 将指针作为参数传递
由于在被调函数内部无法直接修改主调函数的变量。那么我们采用迂回战术,在函数main
中取得a、b的指针。将两个指针传递到函数swap
。那么,在函数swap
内部可以根据这两个信息修改a、b。
这下,我们就需要用到指针类型作为参数了。
#include <stdio.h>
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
int main()
{
int a, b;
int temp;
a = 1;
b = 2;
printf("a=%d b=%d\n", a, b);
// 交换a,b变量
swap(&a, &b);
printf("a=%d b=%d\n", a, b);
return 0;
}
现在将x
、y
改为了int *
类型的指针。在主调函数中,对a
,b
进行取地址获取指针并传入函数swap
。在函数swap
内部,通过这两个指针交换目标数据对象的值。注意,不是交换指针x,y的值,而是交换目标数据对象a,b的值。所以,需要在指针前使用取值运算符*。
图中,红色数值为数据对象首地址,黑框内的为变量名和值。
现在终于能解释为何在使用scanf
函数时,需要对变量先取地址再传入参数了。
int n;
scanf("%d", &n);
scanf
会从读取从键盘的输入,转换后存储到变量n当中。被调函数scanf
无法直接修改在主调函数中的变量n。因此,我们将变量n的指针传入scanf
函数。通过指针使得被调函数间接地修改主调函数中的变量。