指针函数与函数指针
int *fp():fp表示一个函数(指针函数),其返回一个指向int类型的指针,本质是函数。
int (*fp)():fp表示一个函数指针,其指向的函数返回一个int型数据,本质是指针,该指针指向这个函数。也可以描述为“返回值为int类型的函数指针”。
理解(*fp)(),fp(),*((*fp)()),*(fp())
(*fp)(),fp()二者等价,后者是前者的简写,void (*fp)()表示返回值为void类型的函数指针,调用这个函数的时候用(*fp)(),也可简写成 fp()
同理,*((*fp)()),*(fp())二者等价,后者是前者的简写。因为函数运算符()的优先级比单目运算符*高,后者其实等价于 *fp()
fp() | 等价于 (*fp)() |
*fp() | 等价于 *((*fp)())、*(fp()) |
理解(*(void (*)())0)()
我们将 (*(void (*)())0)() 中的 红色部分提取出来,即 void (*)(),先来理解void (*)()。
由于 void (*fp)() 表示返回值为void类型的函数指针,将变量名fp去掉就表示一种变量类型“void (*)()”,即“返回值为void类型的函数指针”这种变量类型(可理解为与int、char一样),可用于强制类型转换,(变量类型) 就表示强制转换成该变量类型,比如将变量a强制转换 :(int)a,(void (*)())a。
所以在(*(void (*)())0)() 中可以继续提取 (void (*)())0,这个表示将0地址强制转换为“返回值为void类型的函数指针”。这里我为什么将0理解成0地址呢?因为将强制转换类型 (void (*)()) 先拿开以后,就剩下 (*0)(),很明显 *0 中的0表示0地址。其实解析到这里后思路也很清晰了,由前面的介绍可知 (*0)() 是函数指针的写法,但是这里的 0 是一个普通的指针变量类型,它不是函数指针类型,所以需要将其强制转换为“返回值为void类型的函数指针”这种类型,也就是 (*(void (*)())0)()。(在 (*0)() 中,运算符*必须要一个指针来做操作数,而且这个指针还必须是个函数指针)
到这里,我们可以思考下,强制转换 (*0)() 为函数指针类型能否写成如下形式呢? ((void (*)())*0)() 或者 ((void (*)())(*0))()
善于利用typedef
(*(void (*)())0)()中的(void (*)())是强制类型转换,可以将其用typedef定义
typedef void (*fp)();
(*(void (*)())0)()就可以写成 (*(fp)0)()