今天在看《深入理解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++]如何解读返回函数指针的函数声明的更多相关文章

  1. C++ —— 返回数组指针的函数 和 返回指向函数的指针的函数

    返回数组指针的函数 基础知识:数组不能被拷贝,函数不能返回数组,只能返回数组的指针或者引用. 定义一个 返回数组指针的函数 的方法,以 一个接收参数为 含有10个整型元素的数组的引用  和 返回一个含 ...

  2. [笔记]C++声明返回数组指针的函数

    数组指针的声明:type (*name)[size]; 由于数组不能拷贝,所以函数不能返回数组.但是函数可以返回指针和引用,所以函数可以返回数组指针或引用. 和数组指针的声明类似: type (*fu ...

  3. C#委托与C语言函数指针及函数指针数组

    C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...

  4. Delphi 函数指针(函数可以当参数)

    首先学习: 指向非对象(一般的)函数/过程的函数指针 Pascal 中的过程类型与C语言中的函数指针相似,为了统一说法,以下称函数指针.函数指针的声明只需要参数列表:如果是函数,再加个返回值.例如声明 ...

  5. C++中的函数指针和函数对象总结

    篇一.函数指针函数指针:是指向函数的指针变量,在C编译时,每一个函数都有一个入口地址,那么这个指向这个函数的函数指针便指向这个地址.函数指针的用途是很大的,主要有两个作用:用作调用函数和做函数的参数. ...

  6. Day8 函数指针做函数参数

    课堂笔记 课程回顾         多态 virtual关键字 纯虚函数 virtual func() = 0;         提前布局vptr指针 面向接口编程 延迟绑定 多态的析构函数的虚函数. ...

  7. typedef void (*Fun) (void) 的理解——函数指针——typedef函数指针

    首先介绍大家比较熟悉的typedef int i;//定义一个整型变量i typedef myInt int: myInt j;//定义一个整型变量j 上面介绍得是我们常用的比较简单的typedef的 ...

  8. C/C++回调方式系列之一 函数指针和函数回调模式

    一.函数指针 1. 函数的定义 return_type function_name(parameter list) { function_body } return_type: 返回值,函数一定有返回 ...

  9. C语言笔记 08_函数指针&回调函数&字符串&结构体&位域

    函数指针 函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调用函数.传递参数. 函数指针变量的声明: / ...

随机推荐

  1. HDFS DATANODE 磁盘容量的最小值

    HDFS的DATANODE的剩余空间具体要到多大?关于这个问题,下面记录下对这个问题的调查 昨天,讨论群里面给出了一个异常: op@odbtest bin]$ hadoop fs -put ../tm ...

  2. Java的Signature签名转换成.Net

    Java: Signature sig = Signature.getInstance("SHA1withRSA"); sig.initSign(rsaPrivateKey); s ...

  3. Linux网络子系统

    再Linux的世界里,万物皆文件,通过虚拟文件系统VFS,程序可以用标准的Linux系统调用对不同的文件系统,甚至不同介质上的文件系统进行读写操作.下面我们揭示Linux网络子系统的秘密 sockfs ...

  4. SpringBoot入门 (一) HelloWorld

    一 什么是springboot springboot是一个全新的框架,它设计的目的简化spring项目的初始环境的搭建和开发,主要有以下几个特点: 1.简化初始配置 ,可与主流框架集成: 2.内置Se ...

  5. java 基本理论知识点

    通过JAVAOO 的笔试后,总结了一些理论的知识点. 1.main方法是怎么写的 public static void main(String [] args){}//最习惯的 public stat ...

  6. Object类上的方法

    1.getClass: public final native Class<?> getClass(); 返回当前对象运行时的类的对象. 2.hashCode: public native ...

  7. spring cloud连载第三篇补充之Zuul

    由于Zuul的内容较多所以单独列出一篇来讲.全是干货,如果学到东西的,动动小手给点个推荐^_^  谢谢! 1. Router and Filter: Zuul(路由和过滤:Zuul) 路由是微服务架构 ...

  8. HTML5的拖放事件

    1.给标签添加属性draggable=ture即可允许拖放,有些标签可以不加,例如img有图片.a有url,默认拥有拖放功能 2.事件在被拖动元素上触发 ondragstart ondrag ondr ...

  9. tcpdump一个命令的剖析

    简单介绍:用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据 ...

  10. Activiti - 设置会签

    前些天在群里聊工作流和Activiti,群里有人分享了自己的工作流引擎开源项目,大伙纷纷问这问那(比如为什么突然自己搞个process engine.有没有eclipse plugin.能不能绘制流程 ...