函数指针的定义
函数在内存中也是有地址的:
#include <stdio.h> void fun() { printf("hello, world\r\n"); } int main(int argc, char* argv[]) { printf("%p\r\n", fun); return 0; }
既然有地址,就可以定义指针存储改地址,存储函数(首)地址的指针,称为函数指针。
函数指针的定义有些特别,比如,定义一个可以指向返回值为int,有一个int参数的函数的指针,声明如下:
#include <stdio.h> int fun(int arg) { printf("hello, world\r\n"); } int main(int argc, char* argv[]) { int(*pfn)(int) = NULL; pfn = fun; return 0; }
函数指针的声明,可以按以下步骤完成:
- 先写出目标函数的原型
- 将目标函数的函数名改为函数指针变量名
- 为“*”号和函数名加括号
函数指针的复杂性
想象一下,如果我们定义了一个函数,其参数是一个函数,返回值也是一个函数,原型分别为:
- 参数:无参数,无返回值
- 返回值:有一个int参数,有一个int返回值
最终完成声明的代码类似如下:
#include <stdio.h> #include <signal.h> void FunArg() { printf("我是没有参数没有返回值的函数\r\n"); } int FunReturn(int arg) { printf("我是int参数,int返回值的函数\r\n"); return 0; } int(*MyFunction(void (* pArg)(void) ))(int) { printf("我是参数及返回值都是函数的函数\r\n"); return FunReturn; } int main(int argc, char* argv[]) { MyFunction(FunArg); return 0; }
因为C语言中函数指针的变量名不处于最末尾,所以函数指针类型组合在一起,显得非常怪异。
为了简化,我们可以使用typedef语法。
typedef
typedef是声明别名的关键字,我们可以使用typedef,为类型起别名。
基本语法是:
typedef <原类型名> <新别名>
新别名的效果与原类型名效果一样
typedef int MYINT; int main(int argc, char* argv[]) { MYINT value = 5; return 0; }
使用typedef可以增强代码的可读性。
特别是对于函数指针而言,函数指针起别名较为特殊,它没有所谓原类型名,typedef之后解的标识符就是新的别名,比如,使用typedef简化我们之前的代码:
#include <stdio.h> #include <signal.h> void FunArg() { printf("我是没有参数没有返回值的函数\r\n"); } int FunReturn(int arg) { printf("我是int参数,int返回值的函数\r\n"); return 0; } typedef void(*PFN_ARG)(void); typedef int(*PFN_RETURN)(int); PFN_RETURN MyFunction(PFN_ARG arg) { printf("我是参数及返回值都是函数的函数\r\n"); return FunReturn; } int main(int argc, char* argv[]) { MyFunction(FunArg); return 0; }
代码的功能与之前完全一样,但是可读性增强了很多。