在上一篇文章中,我们讲解了C语言中一个特殊的指针类型数组指针,这篇文章我们将讲解另一个特殊的指针,函数指针。分为函数指针变量,函数指针数组和函数指针的应用——转移表三个章节。
目录
一 函数指针变量
1 函数的地址
在之前的学习中,我们了解到变量是有地址的,数组也有地址,那函数有没有地址呢?答案是有的,可以看下面这段代码:
#include<stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
int a = 10;
int b = 20;
int ret = Add(a, b);
printf("%d\n", ret);
printf("%p\n", &Add);
printf("%p\n", Add);
return 0;
}
运行结果是:
可以看到打印出了函数Add的地址,而且&Add与Add打印出的地址是一样的,所以&函数明与函数名代表的含义是一致的,都是代表函数的地址。
2 函数指针变量
既然函数是有地址的,那我们就可以用一个函数指针变量来接受一个函数的地址,关键的就是函数指针的类型是什么,下面我们来讲解函数指针的类型。
类比上篇文章讲解的数组指针类型,之前的5个元素的整形数组指针类型是这样的:
int(*p)[5] = &arr;
我们知道数组指针变量旁边的*代表p是一个指针变量,int代表数组元素是整形元素,[5]代表数组里面有5个元素,所以类比数组指针,函数指针变量名旁边应该也有一个*代表变量是个指针变量,而且应该标注函数的返回类型和参数类型,所以函数指针应该这样写(以上面的Add函数为例):
int(*p)(int, int) = Add;
左边的int代表函数的返回类型是int类型,(int, int)代表函数的参数类型,而且由于这里类似于声明函数,所以里面参数里面的变量名是可以不写的,当然写上也是可以的,p旁边的*代表p是一个指针变量,而且是要加上括号代表p是与*结合的,如果不加括号,就会变成以下这种:
int* p(int,int);
这个代码是一个函数声明语句,声明一个函数名为p,参数类型为(int,int),返回类型为int*指针类型,所以如果如果要写函数指针,指针名字与*是必须要加括号的。
二 函数指针数组
既然有了函数指针,那么我们就可以写出函数指针数组了,对比上篇文章的数组指针数组,之前的数组指针数组是这样写的:
int(*p[5])[5];
所以对比数组指针就可以写出函数指针数组了:
#include<stdio.h>
int Add(int x,int y)
{
return x + y;
}
int Sub(int x,int y)
{
return x - y;
}
int Mul(int x,int y)
{
return x * y;
}
int Div(int x,int y)
{
return x / y;
}
int main()
{
int(*prr[4])(int,int) = {Add, Sub, Mul, Div};
int a = 10;
int b = 20;
int ret = prr[0](a ,b);
printf("%d\n", ret);
return 0;
}
运行结果是:
上述代码中的prr数组就是函数指针数组,其数组每个元素的类型是int(*)(int,int),数组元素为4个,同样的,表示数组元素的[4]也必须写在数组名旁边,别的写法是错误的。
需要注意的一点是,函数指针数组中每个元素所指向的数组必须是同一类型的(这里的同一类型指的是返回值类型一样,参数个数与类型也一样),因为函数指针数组的每个数组元素的类型就代表了其指向的函数的返回值与参数个数和类型。
三 函数指针的应用 —— 转移表
函数指针有个特殊的应用就是转移表,以实现计算器为例:
#include<stdio.h>
void meun()
{
printf("*******************\n");
printf("** 1. Add 2. Sub **\n");
printf("** 3. Mul 4. Div **\n");
printf("** 0. exit **\n");
printf("*******************\n");
}
int Add(int x,int y)
{
return x + y;
}
int Sub(int x,int y)
{
return x - y;
}
int Mul(int x,int y)
{
return x * y;
}
int Div(int x,int y)
{
return x / y;
}
int main()
{
int input = 1;
int x = 0;
int y = 0;
int ret = 0;
do
{
meun();
printf("请选择:");
scanf("%d", &input);
int(*p[5])(int,int) = {0, Add, Sub, Mul, Div};
if (input >= 1 && input <= 4)
{
printf("请输入两个操作数:");
scanf("%d%d", &x, &y);
ret = p[input](x, y);
printf("%d\n", ret);
}
else if (input == 0)
printf("退出计算器\n");
else
printf("输入错误,请重新输入\n");
}while(input);
return 0;
}
运行结果是:
在上述这个代码中,可以看到有个函数指针数组指向四个相同类型的函数,分别是加法函数,减法函数,乘法函数,除法函数,通过不同的input值来指向p指针数组中不同的函数指针,近而来调用不同的函数,通过一个函数指针数组来实现了不同函数之间的转移,这就叫做函数的转移表应用。