[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_函数指针&回调函数&字符串&结构体&位域
函数指针 函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调用函数.传递参数. 函数指针变量的声明: / ...
随机推荐
- 使用Second Copy同步ftp服务器的差异文件
公司一直用自主开发的一个同步工具来进行数据库文件异机备份的,但无奈太不稳定,三天两头出现服务挂死的问题,特别是最近这1个月,几天就1次. 问题现象都是服务一直在运行,但没有复制文件到备份机上,而且备份 ...
- springclould nginx转发 websocket400报错问题
之前一直找原因一直围绕着nginx转发的问题 说头信息没设置全 然后nginx配置文件上加了这些 #http块加以下几行: map $http_upgrade $connection_upgrade ...
- 神经网络中的池化层(pooling)
在卷积神经网络中,我们经常会碰到池化操作,而池化层往往在卷积层后面,通过池化来降低卷积层输出的特征向量,同时改善结果(不易出现过拟合).为什么可以通过降低维度呢? 因为图像具有一种“静态性”的属性,这 ...
- GBDT多分类示例
相当于每次都是用2分类,然后不停的训练,最后把所有的弱分类器来进行汇总 样本编号 花萼长度(cm) 花萼宽度(cm) 花瓣长度(cm) 花瓣宽度 花的种类 1 5.1 3.5 1.4 0.2 山鸢尾 ...
- 解决MySQL联表时出现字符集不一样
mysql 建表时都会设置表的字符集和排序规则,通常是 utf8,不过我这边习惯建表的字符集是 utf8mb4,排序规则是 utf8mb4_unicode_ci.有些 utf8mb4 的表默认排序规则 ...
- 【LeetCode题解】142_环形链表2(Linked-List-Cycle-II)
目录 描述 解法一:哈希表 思路 Java 实现 Python 实现 复杂度分析 解法二:双指针 思路 Java 实现 Python 实现 复杂度分析 描述 给定一个链表,返回链表开始入环的第一个节点 ...
- [uva] 1671 History of Languages
题目描述 输入两个DFA,判断是否等价. https://uva.onlinejudge.org/external/16/1671.pdf 输入 第一行T 可以接受的字母表 第二行N 状态数 接下去N ...
- Android源码博客目录
每次都找不到,干脆每个部分都开个目录,方便找 0. 杂项 一些Android的博客,没事翻翻 1. 构建相关 linux和Android的Makefile和android.mk android 目录下 ...
- 使用T4Scaffolding 创建自己的代码生成
nuget查找引入T4Scaffolding.Core 这个是最低层的,没有其他依赖,当然也没有现成的模板 这个有对EF的依赖,自带了生成DBContext的模板 这个自带了一些mvc的contr ...
- win10 uwp 重启软件
在16299支持在软件自己重启,不需要让用户点击关闭然后启动,虽然我还不知道这个有什么用.本文告诉大家如何让软件关闭重新打开. 首先需要使用的版本是 16299 ,然后使用 RequestRestar ...