地址传递
指针类型可以作为函数参数的类型,这时视为把变量的地址传入函数。如果在函数中对这个地址的元素进行改变,原先的数据就会确实地被改变。
#include <stdio.h>
void change(int *p) {
*p = 233;
}
int main() {
int a = 1;
int *p = &a;
change(p);
printf("%d\n", a);
return 0;
}
输出结果:
233
分析:将int型的指针变量p赋值为a的地址,通过change函数把指针变量p作为参数传入,此时传入的实际上是a的地址。在change函数中,使用p修改地址中存放的数据,实际上修改了a本身。当最后输出a时,就已经是改变了的值。
值传递
#include<stdio.h>
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int a = 1, b = 2;
swap(a, b);
printf("%d %d\n", a, b);
return 0;
}
输出结果:
1 2
分析:函数在接收参数时进行的是单向一次性的值传递。
在调用函数时,只是把参数的值传进去,相当于产生了一个副本,对这个副本的操作不会影响main函数中a、b的值。只有在获取地址的情况下对元素进行操作,才能真正地修改变量。
改进代码如下:
#include<stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int a = 1, b = 2;
int *p1 = &a, *p2 = &b;
swap(p1, p2);
printf("%d %d\n", a, b);
return 0;
}
输出结果为2 1,成功达到修改变量的目的。
错误写法1
#include<stdio.h>
void swap(int *a, int *b) {
int *temp;
*temp = *a;
*a = *b;
*b = *temp;
}
int main() {
int a = 1, b = 2;
int *p1 = &a, *p2 = &b;
swap(p1, p2);
printf("%d %d\n", a, b);
return 0;
}
运行截图:
错误原因:在定义int*型的指针变量temp时,temp没有初始化,即指针变量temp中存放的地址是随机的,如果随机地址指向系统工作区,就会出错,而指向系统工作区的概率极大。
改进代码:
#include<stdio.h>
void swap(int *a, int *b) {
int x;
int *temp = &x;
*temp = *a;
*a = *b;
*b = *temp;
}
int main() {
int a = 1, b = 2;
int *p1 = &a, *p2 = &b;
swap(p1, p2);
printf("%d %d\n", a, b);
return 0;
}
错误写法2
#include<stdio.h>
void swap(int *a, int *b) {
int *temp = a;
a = b;
b = temp;
}
int main() {
int a = 1, b = 2;
int *p1 = &a, *p2 = &b;
swap(p1, p2);
printf("%d %d\n", a, b);
return 0;
}
输出结果:
1 2
分析:错误地认为直接把两个地址交换,交换后元素也交换了,认为swap函数交换完地址后main函数的a与b地址也被交换。由于函数参数的传送方式是单向一次性的,main函数传给swap函数的地址其实是一个无符号整型的数,其本身也与普通变量一样只是值传递,swap函数对地址本身进行修改并不能对main函数里的地址进行修改,能够使main函数里的数据发生变化的只能是swap函数中对地址指向的数据进行的修改,对地址本身进行修改其实与之前对传入的普通变量进行交换的函数一样的作用,都只是副本,无法对数据产生实质性的影响。