1.引入
今天又遇到函数指针的使用,翻阅了下资料,回顾下,想着写篇文章总结下吧,先说说定义(并非标准定义,是我自己理解后的)
函数指针:
实际是一个指针,只不过这个指针指向的是一个函数地址(函数名)罢了
格式: int (*funcptr)(int, int);
指针函数:
实际上是一个函数,只不过返回的值为指针类型罢了
格式:int* func(){
/*do something...*/
return int* data;
}
2.分析及举例
2.1 函数指针
直接上演示代码,如下:
可以看出,我用了3中方式进行函数指针的使用,但是方式2和方式3实质是几乎一样的,但是格式还是有一些小小的区别,一般情况下,我们都习惯使用方式2,比较简介明了,总结下,不管是那种方式,其逻辑都分为三步(简称"三步法:一定以,二赋值,三使用"):
1.声明函数指针
方式1: int (*funcptr)(int, int);
方式2:
typedef double (*func)(double, double);
func fptr;
这两个方式各有利弊,方式1优点是简单明了,一看就懂,缺点是每次使用都要重新再同样声明一次(如:int (*funcptr)(int, int));这就不能一劳永逸了,比较繁琐;方式2就是优点是可以一劳永逸,以后需要函数指针对象了,只需要 func fptr2;就行了,fptr2也是一个函数指针,缺点是对于新手来说比较难懂,不过真心推荐这种方式,比较好用,声明一个func类型的函数指针,后续想用了直接func fptr3;便可以,不需要再double (*fptr3)(double, double);声明费事
2.赋值函数指针(也就是将函数地址赋给函数指针,以备后用)
这个没有什么,就一种方式,将函数地址赋给函数指针便可
如上图中的:
func_add = add;
这里需要明白的是,函数名其实也可以看做是一个指针,所以才可以用''=''来给函数指针赋值,因为函数名就代表了函数的地址,这点类似数组名,异曲同工吧。
3.调用函数指针
如上图中的func_add(12, 23);
这个就比较好理解了,其实调用add函数也是add(12, 23);这里只不过换了个名字而已,可以说是换汤不换药
2.2 指针函数
如上,指针函数其实是一个返回数据类型为指针类型的一个函数,如图中的fpp,我们调用的时候直接调用此函数,用对应的数据类型去接受其返回值便可;还需要注意一点的是,在上图代码中,变量s定义在全局,因为当sp = fpp(10, 20);运行完毕后,变量s不能被释放,否则,*sp就是访问非法内存,所以变量s的寿命要比sp长或者最少等于sp,这个大家注意下就行。
【总结】
一句话:函数指针就是一个指针,只不过指向的是函数罢了;指针函数其实就是一个函数,只不过返回值类型是指针类型的罢了
函数指针的应用比较广泛,因为牵扯到回调函数等知识,这个我们后面会继续说到。
案例分享:
我们用三步法分析下这个函数指针,可以看出:
一定义:人家已经给出来了,就是圈出来的部分,我们需要做的就是去实现对应的函数功能,如下
void xxxx(ZLINK_UbusRequest *req, int type, ZLINK_BlobAtter *msg){
/*do something......*/
}
void yyyyy(ZLINK_UbusRequest *req, int ret){
/*do something......*/
}
二赋值:如下便可
ZLINK_UbusReqDataCbInfo *modmsg;//定义对象
modmsg->compleCallBack = yyyyy;
modmsg->dataCallBack = xxxx;
三调用: