C语言程序在编译后,每个函数都有一个首地址(也就是函数第一条指令的地址),这个地址称为函数的指针。可以定义指向函数的指针变量,使用指针变量间接调用函数。
先用一个简单的程序来说明:
#include <stdio.h>
float max(float a,float b)
{
if(a>b)
return a;
else
return b;
}
float min(float a,float b)
{
if(a<b)
return a;
else
return b;
}
main()
{
float a=3,b=6,c;
float (*p)(float a, float b);//定义指针p为指向函数的指针
p=max;//p指向max函数
c=(*p)(a,b); //等效于 max(a,b)
printf("max=%f\n",c);
p=min;//p指向min函数
c=(*p)(a,b); //等效于min(a,b)
printf("min=%f\n",c);
}
运行结果:
在本程序中的详细说明:
(1)语句float (*p)(float a, float b)定义了一个指向函数的指针变量。函数的格式是:返回值为float型,形式参数列表是(float a, float b),p指针定义后,可以指向任何满足该格式的函数。
(2)定义指向函数的指针变量的格式为:数据类型(*指针变量名称)(形式参数列表);
其中数据类型是函数返回值的类型,形式参数列表是函数的形式参数列表。
(3)形式参数列表中,参数名称可以省略。比如,float (*p)(float a, float b),可以写为:float (*p)(float, float);
(4)需要注意的是指针变量名称两边的括号不能省略。
(5)语句p=max;将max函数的首地址值赋给指针变量p,也就是使p指向函数max。C语言中,函数名称代表函数的首地址。
(6)第一个c=(*p)(a,b);语句:由于p指向了max函数的首地址,(*p)(a,b)完全等效于max(a,b)。*p两边的括号不能省略。
(7)语句p=min; 将min函数的首地址值赋给指针变量p。因为p是一个变量,p的值实际上是一个内存地址值,所以可以指向max,也可以指向min,但指向函数的格式必须与p的定义相符合。
(8)将函数首地址赋给指针变量时,直接写函数名称即可,不用写括号和函数参数。
(9)利用指针变量调用函数时,要写明函数的实际参数。
提示:定义一个指向函数的指针变量时,一定要使用括号。比较下面的两个定义:
float (*p)(float a, float b)
float *p1(float a, float b)
第一个语句定义了一个指向函数的指针变量p;第二个语句其实是声明了一个函数p1,p1的形式参数为(float a, float b),返回值为一个float型的指针。
其实为了模块化的设计还可以将指向函数的指针做为函数的形式参数,在调用函数时可以直接以相应的函数名作为实际参数实现。请参考下面的列子:
#include <stdio.h>
float add(float a, float b)
{
return a+b;
}
float subtract(float a, float b)
{
return a-b;
}
float multiply(float a, float b)
{
return a*b;
}
float divide(float a, float b)
{
return a/b;
}
float math(float (*p)(float, float), float a,float b)
{
return (*p)( a, b);//调用的是哪一个函数就返回这个函数的结果
}
main()
{
float a=4.5, b=7.5;
printf("a+b=%f\n", math(add, a,b));
printf("a-b=%f\n", math(subtract, a,b));
printf("a*b=%f\n", math(multiply, a,b));
printf("a/b=%f\n", math(divide, a,b));
}
运行结果: