目录
一、前言
二、理解函数声明
1.问题思考
(*(void(*)())0)();
如果你还不能轻松解决,请看下面的细细分解( • ̀ω•́ )✧
构造这种表达式的基本规则:按照使用的方式来声明
2.什么是声明
声明由类型和声明符组成
①、简单的一个声明
float f,g;
类型:float
声明符:f,g(最简单的声明符就是单个变量)
声明:当对其求值的时候,表达式f,g的类型为浮点数类型
(我们可以在声明符中任意添加“()”,如 float ((f));)
②、声明可以组合
float pa();
float *pb;
float *pa(),(*pb)();
第三行的式子可以看成一二两行的不同组合。在组合时要注意优先级的问题,如这里的()优先级高于*。
③、类型转换符
知道了声明变量的规则,我们就可以轻松得到该变量的类型转化符
基本方法:只需把变量名和末尾的分号去掉即可
3.分析 (*(void(*)())0)()
我们不妨从该函数得功能出发,探讨对该函数的理解。现在开始我们的反向推演
功能:调用储存位置为0的函数
1.我们首先需要一个函数指针,根据声明的使用我们需要声明符和类型:
void(*fp)()
声明符fp,类型void(*)()
2.调用函数
(*fp)()
[注意:函数指针在定义是(*fp)外面的()不可省略,因为优先级的问题。在调用函数时则可以写为fp() ]
3.我们需要一个地址为0的指针代替fp
你可能会这样调用(*0)(),但遗憾的是*只能解引用指针类型变量
4.因此我们需要强制类型转化
我们需要将0的类型转化为函数指针,这样才能调用函数,朝着这个方向,我们写下:
(void(*)()) 0
得到地址为0的函数指针后我们对其调用(* ( void(*)() 0 ) ) ()
5.利用typedef的简化
typedef void(*func)();
(*(func)0);
[注意:函数指针类型的变量在声明时,变量名紧跟*后 。void(*)()func 则是错误的]
这样是不是更加简洁明了呢?