首先让我们来写一个简单的交换函数:
void Swap(int a,int b)
{
int tmp = a;
a = b;
b = tmp;
printf("%d,%d\n",a,b);
}
int main()
{
int a = 10;
int b = 20;
printf("%d,%d\n",a,b);
Swap(a,b);
return 0;
}
运行以上程序,我们会得到想要的结果。但是,如果将Swap函数中的输出语句(printf("%d,%d\n",a,b);)去掉以后,竟然不是我们所期待的答案,此时我们就应该思考所写的程序是否正确,无疑写错了呀,不然怎么会出现我们不想要的结果。让我来分析为什么不正确:
我们的目标是让主函数中的a值变为20,b值变为10;实现的手段是交换函数。
在程序运行时,给a和b分别分配一个内存,其中保存a和b的值,程序运行到Swap函数时,给其中的a和b赋值主函数传过来的值。
进入Swap函数中并运行接下来的程序。
此时我们就可以看出,Swap中a和b的值确实交换了,如果有输出函数的话,就会得到我们想要的结果,但是我们要清楚,我们的目标是主函数中a和b的值进行交换,然而主函数中a和b的值并未发生改变,所以我们的目标还是没有达到。想要修改主函数中a和b的值,我们就需要访问它的地址,由此我们需要借助指针来达到在Swap函数中修改主函数中a和b的值。
void Swap(int *p1,int *p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
int main()
{
int a = 10;
int b = 20;
printf("%d,%d\n",a,b);
Swap(&a,&b);
printf("%d,%d\n",a,b);
return 0;
}
以上才是交换函数的正解,下面让我来给大家分析一下为什么:
红色的表示各个变量的地址。运行主函数时,将主函数中a和b的地址传给Swap函数中的指针变量p1和p2,p1与a建立某种联系,p2与b建立某种联系。接着运行函数Swap的程序。
对*p1(对p1进行解引用)的值赋给tmp,*p2的值赋给*p1,最后将tmp的值赋给*p2,交换完成。现在我们可以看出,主函数中a和b的值发生我们需要的变化,这也意味着我们的目标达到了。
于是我们得到一个结论:一个函数要想修改另一个函数的数据,必须传指针和解引用。
在这里我们还需要注意交换函数的其他两种错误写法:
第一种
void Swap(int *p1,int *p2)
{
int *tmp;//野指针(悬挂指针):没有指向有效(能访问)的地址。
*tmp = *p1;//程序在此处奔溃,不能在*tmp处写数据
*p1 = *p2;
*p2 = *tmp;
}
第二种
void Swap(int *p1,int *p2)
{
int *tmp;
tmp = p1;
p1 = p2;
p2 = tmp;
}