简析令人头大的定义 void (*(*f[])())()
来源:互联网 发布:c语言小游戏.pdf 编辑:程序博客网 时间:2024/05/16 09:03
简析令人头大的定义 void (*(*f[])())()
解析
在v2ex闲逛发现有人在谈怎么学习c语言,有人推荐tcpl,然后写了个反人类的变量定义 void (*(*f[])())()
,这么复杂的定义在c++实际的项目中其实也不常见,反正我喜欢研究下到底是什么,就花了点时间去看看这个定义,其实复杂的变量定义在csdn有一个人详细的解读过,不过凭着三脚猫的功底,我还是按着自己的理解去解读下吧。
首先提取下变量名,这个就是我们实际定义的变量f,我们定义了变量f,但是类型还未知,反正知道是
void (*(*[])())()
类型的定义。
然后呢,我们看到了左侧的*和右侧的[],我们知道在没有()的情况下,类型是倾向于和右侧的[]结合的,那么我们知道f是一个数组(当然可以把它弱化为对数组的指针,一样的)。
为了简化理解,我们修改一下这个变量的定义。
void (*(*f[1])())()
这样我们就很简单的知道,f是一个数组,有1个元素,剩下未知的就是数组元素的类型了。
我们来提取下数组的元素类型:
void (*(*)())()
的确是反人类的类型,我们依旧按步骤走。我们朝着刚把变量名移走的位置看,看到了*(*)()
的类型声明,那么究竟这个类型是什么呢?啥都不像!可是最像什么呢?对,有这个类型的,也只有函数指针了。
我们按着函数指针的方向走,发现右边的()
不就是代表有没参数么!对,这条路肯定走的通,剩下的就是解析函数的返回值类型了,于是我们继续把返回值的类型提取出来:
void(*)()
这样就很清楚了吧,函数的返回值也是一个函数指针,参数空返回值也为空,这样我们就把这个变量的类型给解出来了。
按白话说,这个变量其实是一个数组(指针),里面的每一个元素(指向的元素)都是一个函数指针,所以这个数组的大小其实是可以知道的。然后这个函数指针,参数为空,返回值也是一个函数指针,返回值的函数指针则是一个参数为空,返回值为空的函数指针。
下面写一个简单的函数来验证下上述的想法。
typedef void(*ReturnFunc)();void retfn(){ MessageBox(NULL, "call", "t", MB_OK);}ReturnFunc callfn(){ return retfn;}void param(void (*(*f2[])())()){ f2[0]()();}int main() { void (*(*f1[1])())(); f1[0] = &callfn; f1[0]()(); void (*(*f2[])())() = f1; f2[0]()(); param(f1); return 0;}
- 简析令人头大的定义 void (*(*f[])())()
- 令人头大的单片机延时----这里转一篇关于延时函数的文章看看
- 没有参数的函数f(void)
- void f(int(&p)[3]){} 和void f(int(*p)[3]){}的区别
- void const f() vs void f() const
- 头文件的定义
- 硅谷13大令人惊叹的女性
- void f(n,s)
- 令人吐血的预编译头文件(precompiled header)
- [c++]令人吐血的预编译头文件(precompiled header)
- [c++]令人吐血的预编译头文件(precompiled header)
- ipv6的f分段头说明
- 解密C++令人费解的重复定义错,extern关键字
- void (*f(int, void (*)(int)))(int)
- NodeJS开发的十大令人神奇的项目
- 中国最美的、令人震撼的10大名山
- 大型系统上PHP令人不爽的9大原因
- 深度解析Windows最令人迷惑的两大进程
- 猴子吃桃子【对Java试题库1更正】
- Hadoop数据经Hive汇总计算之后导出到Mysql
- ReactNative开发之DrawerLayoutAndroid组件的使用
- SourceTree的使用方法
- Android小项目之--服务【Service】
- 简析令人头大的定义 void (*(*f[])())()
- CAS+SSO原理浅谈
- First one
- 一台设备上安装多个Mysql服务器
- Picasso 2.5.2 resize 图片不能正常显示。
- 最近很火的OkHttp剥洋葱系列
- 图片生成Gif的golang小工具
- Android 小项目之--使用【AudioManager】类控制音量
- web前端的优化