如果我们想要用C语言写一个可以交换两个整型变量的值函数swap,可能会写出这样的代码:
#include
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 = 1 b = 2
交换后:a = 1 b = 2
我们会发现a,b的值并没有交换成功!
在上面的代码中,我们使用的是按值传递的方式将变量 a 和 b 传递给 swap 函数。按值传递意味着函数接收的是变量的副本,对副本的修改不会影响原始变量。
当调用 swap函数 时,a 和 b 的值被复制到函数 swap 的参数 x 和 y 中。在 swap 函数中,虽然交换了 x 和 y 的值,但这只是在函数内部进行的修改,对原始变量 a 和 b 没有任何影响。
我们再从内存的角度去分析形参x,y和实参a,b的区别:
我们通过以下代码来看看形参和实参的内存地址是否一致:
#include
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= 6422044
&b= 6422040
&x= 6422000
&y= 6422008
我们发现形参x,y和实参a,b的内存首地址均不一样,由此我们可以知道,当我们将a,b传入swap函数时,我们是将a,b的值传入并赋给了形参x,y,保存在x,y对应的内存空间,swap函数实际是对x,y进行了值的交换,与a,b没有关系,由此我们可以发现:实参与形参它们是相互独立的。
既然这样,那我们要怎么样才能实现对a,b变量进行值的交换呢?
为了实现交换 a 和 b 的值,一种常用的方法是使用指针参数。通过传递变量的地址,函数可以直接修改原始变量的值。这样,交换后的结果将在 main 函数中反映出来。
代码如下:
#include
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 = 1 b = 2
交换后:a = 2 b = 1
在这段代码中,我们用取地址运算符&,获取变量 a 和 b 的首地址,并将它们作为参数传递给 swap 函数。在 swap 函数内,我们声明了两个指针变量 x 和 y,并分别将 a 和 b 的首地址赋值给它们,此时指针x指向变量a的位置,指针y指向变量b的位置。在 swap函数中,声明了一个临时变量 temp,用于存储 x 指针所指向的值。通过取值操作符 *
,将 y 指针所指向的值赋给 x 指针所指向的位置,完成 a 和 b 的交换。再通过取值操作符 *,将之前存储在 temp中的值赋给 y 指针所指向的位置,完成交换。
int n;
scanf("%d", &n);