目录
引言
函数指针数组
指向函数指针数组的指针
回调函数
引言
大家好,我是c语言boom成家宝,今天博主带来的依然是指针的进阶讲解。上一篇博客博主有介绍指针,数组指针,指针数组,以及函数指针的概念以及应用,对此还不太了解的小伙伴请移步上一篇,链接:http://t.csdn.cn/eW2yg
函数指针数组
上一篇博客有提到函数指针的使用,那么函数指针数组呢顾名思义就是数组每个元素都是函数指针的类型,就叫做函数指针函数。那么指针函数数组到底可以怎么使用呢?请看以下代码:
#define _CRT_SECURE_NO_WARNINGS 1
#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 (*p1)(int, int) = add; //函数指针
int (*p2)(int, int) = sub;
int (*p3)(int, int) = mul;
int (*p4)(int, int) = div;
return 0;
}
代码思路很简单,就是main函数里使用的函数指针的一个计算机加减乘除的代码展示。但是仔细研究又觉得代码重复部分实在太多,这些代码从主函数到加减乘除四个函数的逻辑和代码格式基本都是相同的,那我能不能把他们直接放在一起,等具体需要什么就可以直接调用什么呢?答案是:当然可以啦。比如我们今天讲解的-----函数指针数组。我们可以在main函数里这样写:
int main() {
//int (*p1)(int, int) = add; //函数指针
//int (*p2)(int, int) = sub;
//int (*p3)(int, int) = mul;
//int (*p4)(int, int) = div;
int (*parr[4])(int, int) = { add,sub,mul,div };//函数指针数组
return 0;
有些小伙伴可能就想说,这样看来没发现函数指针数组有多省功夫啊。那我们不妨把这个简易的计算器功能完全实现出来。相信大家能够看出来上述代码只是实现了计算器的逻辑,还没有传值给它并且把计算结果打印等。那如果我们不使用函数指针数组,实现它的方法只有switch语句,一种情况对应一种计算功能。并且每一种功能都得传值,然后调用函数,再打印结果,实在重复。而且真正的计算器功能肯定也不只有加减乘除四个功能。一直switch下去要写多久?十分冗余!大概代码参照如下图。
所以博主对函数指针数组的方法进行讲解一下。代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#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);
}
void menu() {
//简易菜单,相应选择就进行相应逻辑
printf("**********************\n");
printf("*****1.add****2.sub***\n");
printf("*****3.mul****3.div***\n");
printf("**********************\n");
}
int main(){
menu();
int (*parr[5])(int, int) = { NULL,add,sub,mul,div };//函数指针数组的创建
int x, y;
scanf("%d,%d", &x, &y);//接受两个整数进行计算
int input = 0;
int ret;
do {
menu();
printf("请选择%d", input);
ret = parr[input](x, y);//函数指针数组的应用
printf("%d", ret);//结果
} while (input);
return 0;
}
通过这样的方式我们就可以直接调用自己需要的功能了。如果后续又开发出了新的函数功能,我们只需要添加即可,较传统的switch语句添加就更方便,也更简洁。
指向函数指针数组的指针
int(*p)(int,int)//函数指针
int(*parr[])(int ,int) //函数指针数组
int(*(*p)[])(int,int)=&parr;//&parr函数指针数组的地址,
//p就是指向函数指针数组的指针
当然,这个可以无限套娃一直套下去,因为有地址就有指针,有指针就又有地址。不过基本到这里就已经够用了,再深入套下去也没有意义,也基本没有实用场景,代码可读性也不高。
回调函数
回调函数是一个通过函数指针调用的函数。如果你把函数指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由函数的实现方直接调用,而是特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
比如我们还是上述最开始那个冗余的代码。除了使用函数指针数组来解决冗余的问题以外,我们还可以使用回调函数来解决。我们把switch语句里的内容改成这样:
然后声明Calc()函数,
代码逻辑如下图:简单明了,相信大家自行都能 看懂,博主就是提供一种回调的思想。
回调函数的用处很大,例如c语言中一个经典的库函数qsort,快速排序,就是利用的这个回调的思想。具体快速跑徐是怎么实现的呢博主就留到下一次的博客单独讲解。