如何分析(*(void(*)())0)()
声明
任何C变量的声明都由两部分组成:类型以及一组类似表达式的声明符(declarator)。
声明符
它与表达式类似,对它求值应该返回一个声明中给定类型的结果。最简单的声明显然就是单个变量。
float f,g;
当对其求值时,表达式f
和g
的类型为浮点类型。
这里强调表达式,所以我们也可以这么写:
float ((f));
即当对其求值时((f))
的类型为浮点类型,由此可得f
也是浮点类型。
同理
float ff();
表达式 ff()
求值的结果是一个浮点类型,所有ff()
是一个返回浮点类型的函数。
还有
float *pf;
*pf
这个表达式是一个浮点数,那pf
就是一个指向浮点数的指针。
组合起来还会更有意思
float *g(),(*h)();
()
的优先级比*
高。所以g
是一个返回float
类型指针的函数,h
是一个指向函数的指针,所指函数返回值是浮点型。
类型转换符
只需要将声明中的;
与变量名去掉,再加一个括号即可。
int a;
类型转换符是(int)
float (*h)();
类型转换符是(float (*)())
,它就表示一个指向返回值为浮点型的函数的指针的类型转换符。
分析
- 调用一个函数指针
(*fp)();
这与(*(void(*)())0)()
很相近,可以将(void(*)())0
看作fp
- 现在怎么来理解
(void(*)())0
void (*fp)();
这个声明表示fp
是一个指向返回值为void
的函数的指针。
刚刚说了类型转换符。那么void (*fp)()
的类型转换符就是void (*)()
那么
(void(*)())0;
就是将0
转换成指向返回值为void
的函数的指针
用typedef
更加清晰
typedef void (*FP)();
(*(FP)0)();
是不是很有意思?
应用
这是C程序员经常用到的问题,
signal
函数,接受两个参数,一个是整数,一个是指向用户提供函数的指针。这个函数用于捕捉到特定的signal
signal.h
的库中signal函数是如何声明的?
我们先从用户定义的提供信号处理函数开始:
void sigfunc(int );
那么可以写出一个函数指针
void (*sfp)(int );
那么可以根据两个参数写出
signal(int,void(*)(int));
因为signal
本身也是一个函数且返回值也为void
,可以用它替换sfp
void (*signal(int,void(*)(int)))(int );
同样,也可以用typedef
typedef void (*HANDLER)(int);
HANDLER signal(int,HANDLER);