列子中,老师就是main函数,而班长是swap函数,两位同学的宿舍号就是swap函数的形参,老师告诉班长同学宿舍号就是参数传递的过程。
##2、源码实现
/*this programmer is used to compear 2 double num, and output which is max and which is min*/
#include
int main()
{
void swap(double *p1, double *p2);
double a = 0, b = 0, *p1 = &a, *p2 = &b;
scanf("%lf%lf", &a, &b);
if(*p1 < *p2)//也可以写为if(a < b){ swap(&a, &b);}
{
swap(p1, p2);
}
printf("max = %lf\nmin = %lf\n", *p1, *p2);
return 0;
}
void swap(double *p1, double *p2) //形参p1,p2是指针变量
{
double temp;
temp = *p1;//通过指针访问了main空间的内容
*p1 = *p2;//通过指针访问和修改了main空间的内容
*p2 = temp;//通过指针修改了main空间的内容,并把swap函数的数据temp传回了main
}
代码解析:
swap函数的形参p1,p2前都有*
标识,表明当函数被调用时,p1和p2将被作为swap函数的指针变量(而不是普通变量),p1和p2中只能保存地址,不能保存普通数据。这里形参名为p1和p2,不能说成是*p1
和*p2
。main函数对swap函数的调用语句是swap(p1,p2)
,这里将p1的值(地址)传给p1,将p2的值(地址)传给p2。
swap函数通过参数p1,p2获得了a,b的地址,在swap函数中,通过这两个地址就可以任意存取a,b这两个变量了,而不论a,b这两个参数位于哪个函数。
temp = a;a = b;b = temp;
是不行的。在swap中只能通过地址的方式访问它们。void swap(double *p1, double *p2)
{
int *temp;
temp = p1;
p1 = p2;
p2 = temp;
}
不能达到预期结果,因为这只交换了p1和p2的值,只是交换了他们的储存空间,没有交换内容,并且本身修改后不能传回实参,即不能传到main函数。
###②错误类型二
void swap(double *p1, double *p2)
{
double *temp;
*temp = *p1;
*p1 = *p2;
*p2 = *temp;
}
上述方式,定义了一个未知空间temp,并且通过指针修改了其数据。如果temp中存的是非常重要的内容,那么程序就会出问题,所以这种方法也是非常不可取的。
###③错误类型三
void swap(double x, double y)
{
int temp;
temp = x;
x = y;
y = temp;
}
这种方式,只能单向传递,就是把main函数中想,x,y对应的值传到swap函数中,而不能传回交换后的值。
##4、主调函数传回数据的第二种方式
先看代码
#include
int main()
{
void fun(int a, int b, int *sum, int *sub);
int a = 0, b= 0, m1,m2;
scanf("%d%d", &a, &b);
fun(a, b, &m1, &m2);
printf("sum = %d\nsub = %d\n", m1, m2);
}
void fun(int a, int b, int *sum, int *sub)
{
int p, q;
p = a + b;
q = a - b;
*sum = p;
*sub = q;
}
这里直接用指针返回和与差,而没有用到return。
#二、数组做函数参数
数组做函数参数,说具体是指向数组的指针变量做函数参数。
由于数组名是该数组的首地址,指针变量的值也是首地址,所以函数的实参和形参都可以指向数组名或者数组的指针。于是有了以下四种对应关系:
数组名和数组指针做函数参数时的对应关系
实参 | 形参 |
---|---|
数组名 | 数组名 |
数组名 | 指针变量 |
指针变量 | 指针变量 |
指针变量 | 数组名 |
下面用一段代码来说明问题:
#include
int main()
{
float ave(int *b, float num);
int counter,a[5] = {0};
float all =0, res;
scanf("%f", &all);
for(counter = 0; counter < all; counter++)
{
scanf("%d", &a[counter]);
}
res = ave(a, all);
printf("%f", res);
return 0;
}
float ave(int *b, float num)
{
int i, sum =0;
float ave;
for(i = 0; i < num; i++)
{
sum = sum + b[i];
}
ave = (float)sum/num;
return ave;
}
这里传入函数ave的是数组a的首地址,而不是将整个数组传入。传入首地址后,ave函数就按照一定顺序去访问a的储存空间,从而得到a中的数据。
float ave(int *b, float num)
也可以写为float ave(int b[], float num)
或者float ave(int b[100], float num)
也就是说b[]
后面方括号内可以是任意数字,因为那个数字是没有意义的,真真起作用的是b和方括号。int (*pf)();
上述语句就是对一个函数的指针的定义,它可以且只能保存函数的首地址。并且该函数的返回值是int形的。当然也可以在后面的()中加上函数的参数如int (*pf)(int , int )
下面介绍一个很重要的定义形式逆序阅读法
int (*pf)();
有()先读()内的内容,读作:pf是指针,指向函数,函数返回值是int。
int *pf();
()
比*
优先, 先读()
后读*
, 读作pf
是函数, 其返回值是int *
int pf();
先读(),读作pf
是函数,函数返回值是int。
##2、变量指向函数及函数调用
让指针变量指向函数的方法如下:
pf = 函数名;
注意了,这里是干干净净的,没有任何零碎。
不要写为pf = &函数名
, 或者*pf = 函数名;
。
通过函数指针调用函数的方法如下:
(*pf)(参数,参数,.......);
或:
pf(参数,参数,....);
注意,调用函数时用(*pf), 或者直接用pf, 均可。(*pf)的*
仍然是一个标志,不是取其内容。
##3、示例
#include
int main()
{
int max(int a,int b);
int (*pmax)();
int x, y, z;
pmax = max;
printf("input two numbers:");
scanf("%d%d", &x, &y);
z = (*pmax)(x, y);
printf("maxmum = %d", z);
return 0;
}
int max(int a, int b)
{
if(a > b)
{
return a;
}
else
{
return b;
}
}
部分编译器,不支持函数的指针。
送福利了