数据交换在C语言中十分常见。作为初学者首先学的应该都是如下方式:
int main()
{
int a = 10;
int b = 20;
int tmp = a;
a = b;
b = tmp;
printf("%d,%d\n",a,b);
return 0;
}
这种交换如果放在一个函数中没错,但如果将它们分别放在子函数和主函数中就会发生错误。
错误示例1:
void Swap(int a,int b)
{
int tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 10;
int b = 20;
Swap(&a,&b);
printf("%d,%d\n",a,b);
return 0;
}
其结果是打印出来的a,b值并没有交换。这是因为在子函数中定义的形参(a b)和主函数中的实参(a b)虽然函数名相同,但是其地址并不相同。导致的结果是子函数交换的是形参的数值,对主函数中实参的数值结果并不影响,所以输出的结果没有交换。
错误示例2:
void Swap(int *p1,int *p2)
{
int *tmp = p1;
p1 = p2;
p2 = tmp;
}
int main()
{
int a = 10;
int b = 20;
Swap(&a,&b);
printf("%d,%d\n",a,b);
return 0;
}
这个函数的输出结果也是a,b值没有交换。首先定义两个整形指针*p1,*p2它们分别指向a,b(p1=&a ,p2=&b)。定义一个整形指针*tmp。将变量p1的值赋给指针tmp(变量p1的值为a的地址,因为并没有解引用),将变量p2的值赋给p1(p2的值为b的地址),再将变量tmp的值赋给p2。这样操作下来实际只是将p1,p2保存的地址交换,结果由原来p1=&a ,p2=&b变为现在p1=&b,p2=&a。所以a,b的值并没有改变。
错误示例3:
void Swap(int *p1,int *p2)
{
int *tmp;//野指针(悬挂指针)
*tmp = *p1;//崩溃
*p1 = *p2;
*p2 = *tmp;
}
int main()
{
int a = 10;
int b = 20;
Swap(&a,&b);
printf("%d,%d\n",a,b);
return 0;
}
错误三中定义的整形指针*tmp未被初始化,形成了一个野指针(也叫悬挂指针),你没有访问权限的地址(指针),这个指针有可能不存在,也有可能存在但是你不能访问。在出现野指针后,整个程序会崩溃,无法输出你想要的结果。
正确示例:
#include<stdio.h>
void Swap(int *p1,int *p2)
{
int tmp;
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
int main()
{
int a = 10;
int b = 20;
Swap(&a,&b);
printf("%d,%d\n",a,b);
return 0;
}
tmp = *p1;意思为将a的值赋给tmp,所以
void Swap(int *p1,int *p2)
{
int tmp;
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
的本质是
int tmp = a;
a = b;
b = tmp;
只不过是通过指针的方式将主函数的数据修改为子函数的数据。换句话说:子函数的改变要想影响主函数的数据必须传指针和解引用.