先描述一个题目,题目是这样的,输入a和b两个整数,按先大后小的顺序输出a和b。
/* Note:Your choice is C IDE */
#include "stdio.h"
void main()
{
void swap(int *p1,int *p2);
int a,b;
int *pointer_1,*pointer_2;
scanf("%d,%d",&a,&b);
pointer_1=&a;
pointer_2=&b;
if(a<b) swap(pointer_1,pointer_2);
printf("\n%d,%d\n",a,b);
}
void swap(int *p1,int *p2)
{
int temp;
temp=*p1;
*p1=*p2;
*p2=temp;
}
对程序的说明:swap是用户定义的函数,它的作用是交换两个变量(a
和b
)的值。swap函数的两个形参p1
、p2
是指针变量。程序运行时,先执行main函数,输入a
和b
的值。然后将a
和b
的地址分别赋给指针变量pointer_1
和pointer_2
,使pointer_1
指向a
,pointer_2
指向b
。接着执行if语句,若满足a
<b
,则执行swap函数。注意实参pointer_1
和pointer_2
是指针变量,在函数调用时,将实参变量的值传送给形参变量,采取的依然是”值传递”方式。因此虚实结合后形参p1
的值为&a
,p2
的值为&b
。这时p1
和pointer_1
都指向变量a
,p2
和pointer_2
都指向b
。接着执行swap函数的函数体,使*p1
和*p2
的值互换,也就是使a
和b
的值互换。函数调用结束后,形参p1
和p2
不复存在(已释放)。最后在main函数中输出的a
和b
的值已是经过交换的值。
请注意交换*p1
和*p2
的值是如何实现的。如果写成以下这样就有问题了:
void swap(int *p1,int *p2)
{
int *temp;
temp=*p1; /*此语句有问题*/
*p1=*p2;
*p2=temp;
}
*p1
就是a
,是整型变量。而*temp
是指针变量temp
所指向的变量。但temp
中并无确定的值(它的值是不可预见的),因此temp
所指向的单元也是不可预见的。所以,对*temp
赋值有可能给一个存储着重要数据的存储单元赋值,这样就会破坏系统的正常工作状况。应该将*p1
的值赋给一个整型变量,用整型变量temp
作为临时辅助变量实现*p1
和*p2
的交换。
考虑一下是否可以通过下面的函数实现a和b的互换:
void swap(int x,int y)
{
int temp;
temp=x;
x=y;
y=temp;
}
如果在main函数中调用swap函数:
swap(a,b);
在函数调用时,a
的值传送给x
,b
的值传送给y
。执行完swap函数后,x
和y
的值是互换了,但并未影响到a
和b
的值。在函数结束时,变量x
和y
释放了,mian函数中的a
和b
并未互换。也就是说,由于“单向传送”的“值传递”方式,形参值的改变不能使实参的值随之改变。
为了使在函数中改变了的变量值能被main函数所用,不能采取上述把改变的值的变量作为参数的办法,而应该用指针变量作为函数参数,在函数执行过程中使指针变量所指向的变量值发生变化,函数调用结束后,这些变量值的变化依然保留下来,这样就实现了“通过调用函数是变量的值发生变化,在主调函数(如:main函数)中可以使用这些改变了的值”的目的。
请注意,不能企图通过改变指针形参的值而使指针实参的值改变。下面的程序:
/* Note:Your choice is C IDE */
#include "stdio.h"
void main()
{
void swap(int *p1,int *p2);
int a,b;
int *pointer_1,*pointer_2;
scanf("%d,%d",&a,&b);
pointer_1=&a;
pointer_2=&b;
if(a<b) swap(pointer_1,pointer_2);
printf("\n%d,%d\n",a,b);
}
void swap(int *p1,int *p2)
{
int *p;
p=p1;
p1=p2;
p2=p;
}
程序编写者的意图是:交换pointer_1
和pointer_2
的值,使pointer_1
指向值大的变量。其设想是:
- 先使
pointer_1
指向a
,pointer_2
指向b
。 - 调用swap函数,将
pointer_1
的值传给p1
,pointer_2
传给p2
. - 在swap函数中使
p1
与p2
的值交换。 - 形参
p1
、p2
将地址传回实参pointer_1
和pointer_2
,使pointer_1
指向b
,pointer_2
指向a
。然后输出*pointer_1
和*pointer_2
。
但是,这是办不到的,结果并不会发生交换。问题出在第四步。C语言中实参变量和形参变量之间的数据传递时单向的“值传递”方式。指针变量作函数参数也要遵循这一规则。不可能通过调用函数来改变实参指针变量的值,但可以改变实参指针变量所指变量的值。我们知道,函数的调用可以(而且只可以)得到一个返回值(即函数值),而运用指针变量作参数,可以得到多个变化了的值。如果不用指针变量是难以做到这一点的。