[C/C++]如何解读返回函数指针的函数声明
今天在看《深入理解C++11》的时候,看到一段有意思的代码:
int (*(*pf())())() {
return nullptr;
}
我立刻就懵了——从来没有见过这样的函数声明。那么它究竟是一个怎样的函数呢?我努力回忆起《C专家编程》一书的内容,把其中解读变量声明的方法应用于该函数上,最终读懂了该函数。下面是大致的解读过程。
首先,要确定声明中出现的操作符的优先级。显然,函数调用操作符()的优先级是高于指针解引用操作符*的。另外,小括号总是具有最高优先级。
其次,要确定在声明中标识符与某个操作符结合起来的时候有什么意义。例如:
a() a是一个函数
*a a是一个指针
由于函数声明的特殊性,当指针解引用操作符*与一个表示函数的标识符结合时,表示这个函数的返回值是一个指针。例如 *a() 表示a是一个返回值为指针的函数。
有了以上的基础,接下来我们就可以从声明中的标识符开始,按照操作符的优先级,由内向外逐步来解读:
pf() pf是一个无参数函数
* pf() pf是一个无参数函数,它的返回值是一个指针
( * pf() ) () pf是一个无参数函数,它的返回值是一个无参数函数的指针
* ( * pf() ) () pf是一个无参数函数,它的返回值是一个无参数函数的指针,这个函数的返回值又是一个指针
( * ( * pf() ) () ) () pf是一个无参数函数,它的返回值是一个无参数函数的指针,这个函数的返回值又是一个无参数函数的指针
int ( * ( * pf() ) () ) () pf是一个无参数函数,它的返回值是一个无参数函数的指针,这个函数的返回值又是一个无参数且返回值为int的函数的指针。
最终的解读结果冗长拗口。可以看出,这实际上是返回值为函数指针的函数的递归声明。下面是可读性更强的等效代码:
typedef int (*pa)();
typedef pa (*pb)();
pb pfex() {
return nullptr;
}
下面是验证解读结果的测试代码。不得不说,测试代码也不容易理解……
#include <iostream> int a() {
return ;
} int (*b())() {
return a;
} int (*(*pf())())() {
return b;
} typedef int (*pa)();
typedef pa (*pb)();
pb pfex() {
return b;
} int wmain() { int r = pf()()();
std::wcout << r << std::endl; r = pfex()()();
std::wcout << r << std::endl;
}
最终的输出是两个数字29。
[C/C++]如何解读返回函数指针的函数声明的更多相关文章
- C++ —— 返回数组指针的函数 和 返回指向函数的指针的函数
返回数组指针的函数 基础知识:数组不能被拷贝,函数不能返回数组,只能返回数组的指针或者引用. 定义一个 返回数组指针的函数 的方法,以 一个接收参数为 含有10个整型元素的数组的引用 和 返回一个含 ...
- [笔记]C++声明返回数组指针的函数
数组指针的声明:type (*name)[size]; 由于数组不能拷贝,所以函数不能返回数组.但是函数可以返回指针和引用,所以函数可以返回数组指针或引用. 和数组指针的声明类似: type (*fu ...
- C#委托与C语言函数指针及函数指针数组
C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...
- Delphi 函数指针(函数可以当参数)
首先学习: 指向非对象(一般的)函数/过程的函数指针 Pascal 中的过程类型与C语言中的函数指针相似,为了统一说法,以下称函数指针.函数指针的声明只需要参数列表:如果是函数,再加个返回值.例如声明 ...
- C++中的函数指针和函数对象总结
篇一.函数指针函数指针:是指向函数的指针变量,在C编译时,每一个函数都有一个入口地址,那么这个指向这个函数的函数指针便指向这个地址.函数指针的用途是很大的,主要有两个作用:用作调用函数和做函数的参数. ...
- Day8 函数指针做函数参数
课堂笔记 课程回顾 多态 virtual关键字 纯虚函数 virtual func() = 0; 提前布局vptr指针 面向接口编程 延迟绑定 多态的析构函数的虚函数. ...
- typedef void (*Fun) (void) 的理解——函数指针——typedef函数指针
首先介绍大家比较熟悉的typedef int i;//定义一个整型变量i typedef myInt int: myInt j;//定义一个整型变量j 上面介绍得是我们常用的比较简单的typedef的 ...
- C/C++回调方式系列之一 函数指针和函数回调模式
一.函数指针 1. 函数的定义 return_type function_name(parameter list) { function_body } return_type: 返回值,函数一定有返回 ...
- C语言笔记 08_函数指针&回调函数&字符串&结构体&位域
函数指针 函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调用函数.传递参数. 函数指针变量的声明: / ...
随机推荐
- Android 开发工具类 09_SPUtils
SharedPreferences 辅助类: 1.保存在手机里面的文件名: 2.保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法: 3.得到保存数据的方法,我们根据默认值 ...
- 基于线程实现的生产者消费者模型(Object.wait(),Object.notify()方法)
需求背景 利用线程来模拟生产者和消费者模型 系统建模 这个系统涉及到三个角色,生产者,消费者,任务队列,三个角色之间的关系非常简单,生产者和消费者拥有一个任务队列的引用,生产者负责往队列中放置对象(i ...
- Keepalived配置与使用--转载
作者: JeremyWei | 可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明 网址: http://weizhifeng.net/using-keepalived.html 介绍 ...
- canvas文字自动换行、圆角矩形画法、生成图片手机长按保存、方形图片变圆形
canvas的文字自动换行函数封装 // str:要绘制的字符串 // canvas:canvas对象 // initX:绘制字符串起始x坐标 // initY:绘制字符串起始y坐标 // lineH ...
- ruby字符串连接
malls = Mall.allcount = 0malls.each do |mall| count += 1 if mall.parent_ids[0] province ...
- rails安全性
如果你发布你的blog.那么其他人就可以随便修改和添加博客了. Rails提供了一个非常简单的http认证系统,可以非常有帮助的解决这种情况. 在PostsController里面我们需要一个方法阻止 ...
- BATJ面试必会之并发篇
一.线程状态转换 新建(New) 可运行(Runnable) 阻塞(Blocking) 无限期等待(Waiting) 限期等待(Timed Waiting) 死亡(Terminated) 二.使用线程 ...
- Spring4 MVC ContentNegotiatingViewResolver多种输出格式实
前段时间在一个项目里面发现,针对Excel的处理没有一个公用的视图,来个下载的需求就要自己去写一堆POI的东西,终于有一天给我也来了几个,还是按照以前的方式来写,写多了真心想吐,后面想想还是有必要整个 ...
- Node.js函数
Node.js 函数 在JavaScript中,一个函数可以作为另一个函数的参数.我们可以先定义一个函数,然后传递,也可以在传递参数的地方直接定义函数. Node.js中函数的使用与Javascrip ...
- CentOS普通用户没有sudo权限
sudo是linux系统管理指令,是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具,如halt,reboot,su等等.这样不仅减少了root用户的登录 和管理时间,同样也提高了安全 ...