一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是函数指针。
函数指针的定义形式为:
retrunType(*pointerName)(param list); //数据类型(*指针变量名)();
//注意与二维数组的指针的定义区别开(int (*p)[4] = a;)
returnType 为函数返回值类型,pointerNmae 为指针名称,param list 为函数参数列表。参数列表中可以同时给出参数的类型和名称,也可以只给出参数的类型,省略参数的名称,这一点和函数原型非常类似。
注意()
的优先级高于*,第一个括号不能省略,如果写作returnType *pointerName(param list);
就成了函数原型,它表明函数的返回值类型为returnType *
。
比如
int *fun(int a,int b); //返回值是int类型指针的函数
int (*p)(int a,int b); //一个指向函数的指针
【实例1】用指针实现对函数的调用
#include <stdio.h>
//返回两个数中较大的一个
int max(int a, int b){
return a>b ? a : b;
}
int main(){
int x, y, maxval;
//定义函数指针
int (*pmax)(int, int) = max; //也可以写作int (*pmax)(int a, int b)
printf("Input two numbers:");
scanf("%d %d", &x, &y);
maxval = (*pmax)(x, y);
printf("Max value: %d\n", maxval);
return 0;
}
运行结果:
Input two numbers:10 50↙
Max valu:50
第 14 行代码中pmax 是一个函数指针,在前面加 * 就表示对它指向的函数进行调用。
【实例2】
#include <stdio.h>
double f1(double x)
{ return x*x; }
double f2(double x, double y)
{ return x*y; }
double fun(double a, double b)
{
double (*f)();
double r1, r2;
f = f1 ; //函数指针的赋值
//f=&f1; //第二种赋值方法
r1 = f(a); //函数指针第一种调用方法,也可以写成 r1=(*f)(a);
f = f2 ;
r2 = (*f)(a, b); //函数指针第二种调用方法,也可以写成 r2=f(a,b);
return r1 + r2;
}
void main()
{ double x1=5, x2=3, r;
r = fun(x1, x2);
printf("\nx1=%f, x2=%f, x1*x1+x1*x2=%f\n",x1, x2, r);
}
运行结果:
x1=5.000000, x2=3.000000, x1x1+x1x2=40.000000
double(*f)();代表一个指向函数的指针变量; f=f1; 表示把函数f1赋值给f;
注意:
(1)在给函数指针变量赋值时,只需给出函数名而不必给出参数值,因此直接令 f=f1 即可;
(2)注意上面代码的注释部份,赋值和调用的方法都有两种,两种都是可以的。
对于函数指针的赋值:函数名是一个地址,可以将他赋值给一个指向函数的指针。前面加了&符号其意义是一样的。比如定义一个数组arr[],arr表示这个数组的首地址,但&arr同样表示他的首地址。
对于函数指针的调用:比如你定义一个字符串指针char *str, 输出str 他并不是输出了地址,而是输出存在该地址的值。