C语言是一门面向过程的语言,而面向过程最大的利器就是函数,今天我们就来研究一下函数指针相关的话题。
1. 函数指针
首先看一个例子。
#include <stdio.h>
#include <stdlib.h>
int add(int x, int y) {
return x + y;
}
int main() {
int a = 10;
int b = 10;
//
printf("%p\n", add);
printf("%p\n", &add);
system("pause");
return 0;
}
运行结果:
由结果我们可以得出一个结论:
函数名也是函数的指针。
但是呢,这不是我们今天要要讨论的函数指针,就像之前我们研究过的数组指针,那数组名也是指向数组的指针,但它却不是我们要研究的数组指针。而函数名在这里就相当于数组名。
接下来,我们看一看我们今天要研究的函数指针。
定义一个函数指针
int add(int a, int b)
{
int ret = a + b;
printf("%d\n", ret);
return ret;
}
int main()
{
// 一个名为 p ,参数为两个 int 的函数指针
int (*p)(int, int);
p = add;
p(2, 3);
return 0;
}
其实也挺简单的,下一个例子。
(*(void(*)())0)();
它代表了什么?
逐一进行分析。
再看一个例子。
void (*signal(int,void(*)(int)))(int)
// 它代表了什么?
// 答案:
// 返回类型为 void (*)(int) void类型的参数为int的函数指针
// 函数名为 signal(int ,void(*)(int))
//改造一下
typedef void(*func_p)(int); //func_p是一个类型重命名
func_p signal(int ,func_p);
接下来,我们进阶一下,研究一下函数指针的数组和指向函数指针数组的指针,对于函数指针和数组指针不太明白的可以参考一下这篇文章。
2. 函数指针的数组
函数指针的数组,顾名思义,数组里存放的元素都是指针,这些指针的类型为函数指针类型。
看下面的示例:
void test(int a,char c);
void test2(int a,char c);
void test3(int a,char c);
// 定义一个函数指针数组,类型为 void(* )(int,char)
void (*p[3])(int,char) = {test,test2,test3};
//调用函数指针的数组
p[1](1,'2');
拥有了函数指针数组,我们可以将它应用到很多的场景下,如下面的例子
使用函数指针数组编写一个计算器:
//计算器
int add(int a,int b);
int sub(int a,int b);
int mul(int a,int b);
int div(int a,int b);
void menu_end(void);
void menu_start(void);
int main()
{
int x = 0;
int y = 0;
int input = 0;
int flag = 0;
//转移表
int (*pfunarr[5])(int ,int) = {NULL,add,sub,mul,div};
do
{
menu_start();
scanf("%d",&input); //算法
scanf("%d%d",&x,&y); //数值
printf("result = %d\n",pfunarr[input](x,y));
menu_end();
scanf("%d",&flag); //是否继续
}while(flag);
return 0;
}
3. 指向函数指针数组的指针
这个很简单,即一个指向 函数指针数组 的指针,我们要注意的是它的指针类型。
void (*(*ptr)[3])(int ,char ) = &p
//ptr是一个数组,指向一个数组
// 该数组是一个函数指针数组,每个元素是一个函数指针,
// 指针指向一个返回类型为void,参数为 int,char 的函数