自学到线程池 被各种函数指针的套娃操作套蒙了, 所以写一篇来总结一下。
首先要搞清楚几个事情
函数指针和指针函数
函数指针是指针,可以指向任一“同类型”的函数
指针函数是函数,这个函数的返回值是指针 如 int * max(int , int );
钩子函数实际上就是函数指针,首先看下什么是函数指针:
1.函数指针:
函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针
有两个用途:调用函数和做函数的参数。(来自百度百科)
2.函数指针的声明方法
返回值类型 ( * 指针变量名) ([形参列表]);
举例如下图(pFun 应该是function pointer的缩写吧,我看到好多资料都这么命名,所以我照猫画虎)
这个时候我们就可以来使用一下
#include
//函数功能模块
int max(int a, int b){
if(a > b)
return a;
return b;
}
int min(int a, int b){
if(a > b)
return b;
return a;
}
int main(int argc, char *argv[]){
//根据上面的功能函数具有的特征来定义一个函数指针 (函数指针就是指向函数的指针!!!!别绕晕了)
int (*pFun)(int x, int y);
int a = 1;
int b = 2;
int ret;//定义一个变量来接收调用函数后的返回值
/**
* 关键 开始挂钩了!!!这就是挂钩操作
* 把max函数的地址交给pFun这个指针一份,相当于我把max的入口交给了pFun,这样通过pFun就可以使用max
**/
pFun = max;
ret = pFun(a, b);//相当于直接调用max(a,b);
printf("%d\n", ret);
return 0;
}
这个时候我们就会简单的使用钩子函数了, max和min这两个函数就是钩子函数, pFun = max这个操作就叫挂钩子,辛辛苦苦搞懂了这个钩子函数,感觉然并卵,想让钩子函数功能更强大更灵活,就必须介绍下面这步 注册!其实就是把挂钩子这个操作从main函数中拿出来,单独搞了个函数,这个函数的参数就是指向函数的指针(即函数指针)。
注册函数长这样
int RegFun( int (* pFun)(int x, int y) );//这括号里面不就是函数指针吗
上面百度百科也说了钩子函数的作用就两个
1.调用函数(上面的例子已经说明如何调用函数)。
2.作为函数的参数(下面这个注册函数就体现了钩子函数的第二个作用)。
#include
int (*global_pFun)(int a, int b);//由于后面要在注册函数中进行挂钩操作,所以把这个函数指针定义成全局变量
//括号内的int (*pFun)(int a, int b) 是一个函数指针形参(符合这个指针的函数都可以被作为参数传进来)
int RegFun(int (*pFun)(int a, int b)){
global_pFun = pFun;
return 0;
}
//函数功能
int max(int a, int b){
if(a > b)
return a;
return b;
}
int min(int a, int b){
if(a > b)
return b;
return a;
}
int main(int argc, char **argv){
int a = 1;
int b = 2;
int ret;
RegFun(max);//和max挂钩
ret = global_pFun(a, b);
printf("%d\n", ret);
return 0;
}
内心os 写完感觉是在脱裤子放屁一样 传来传去的
下面就是参考文末链接中 大神的例子了 当我们在实际应用中,某一平台要执行某一操作,但这个操作还不确定是什么(没有实际经验的我个人理解应该像是任务系统吧,比如你有新手任务和成长任务还有七日任务,这个时候你就需要这么一个玩意儿(RegFun)来暂时 顶一下 大家都是任务,但是还不确定是哪一类。 如果我说的不对欢迎大家指正我哈,自学渣渣全靠猜测的)
所以实用型的钩子函数诞生了
#include
int (*g_pFun)(int a, int b);//由于后面要在注册函数中进行挂钩操作,所以把这个函数指针定义成全局变量
//单独看这个函数是完全不知道要对x, y做什么操作的,所以可猜测到main函数里的情况一定是先挂钩(知道自己做什么)再调用plat函数
void plat(){
int x = 1;
int y = 2;
int ret;
ret = g_pFun(x, y);//这里要和什么功能挂钩我们暂时不知道
printf("%d\n",ret);
}
//这里开始挂钩 括号内的int (*pFun)(int a, int b) 是一个函数指针形参(符合这个指针的函数都可以被作为参数传进来)
int RegFun(int (*pFun)(int a, int b)){
g_pFun = pFun;
return 0;
}
//函数功能
int max(int a, int b){
if(a > b)
return a;
return b;
}
int min(int a, int b){
if(a > b)
return b;
return a;
}
int main(int argc, char **argv){
RegFun(max);//这里就是执行具体操作的地方咯
plat();
RegFun(min);
plat();
return 0;
}
钩子函数的精妙之处在于我们无法修改平台上的任何数据,只能通过注册函数调用功能模块提供的函数,决定对数据进行什么操作。
推荐参考博客1
推荐参考博客2