今天在看redis源码的时候发现这样的一种函数定义方法,就是将函数作为类型来定义,然后在结构体当中使用
typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);
typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData); typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData); typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);
typedef struct aeFileEvent {
int mask; /* one of AE_(READABLE|WRITABLE) */ aeFileProc *rfileProc; aeFileProc *wfileProc; void *clientData; } aeFileEvent;实际上展开之后就是如下的代码
typedef struct aeFileEvent {
int mask; /* one of AE_(READABLE|WRITABLE) */void *rfileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);
void *wfileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask); void *clientData; } aeFileEvent;如此定义主要是避免对同一原型函数的重复定义,这样就没必要在需要调用void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);此类原型的函数时多次定义,简化了代码,也实现的函数原型的复用。
关于函数指针,实际上其类型是一个int类型的数值,可以在函数指针跟整形之间任意的转换
#include <stdio.h>
typedef int (*add_func_type)(int a, int b);
struct MyStruct{ int m; }; int add(int a, int b) { return a+b; } int main() { struct MyStruct test; test.m = add; add_func_type func = test.m; printf("%d\n", func(1,2)); printf("%d\n", ((add_func_type) test.m)(1,2)); return 0; }将函数名复制给int类型的数据,其本质就是将函数的指针复制给test.m,也就是说test.m实际上也是指向的add函数,然后将函数指针func也指向函数add,这样test.m还是func都指向add函数,只是func是 add_func_type函数指针类型,而test.m是int类型,这样需要将test.m进行强制类型转换,将其转换成函数指针类型的,实现对函数add的调用。当然在编译的过程中会出现一些警告信息,但是最终只是为了说明,函数指针和整形之间具有某种关系。