在《C陷阱与缺陷》第二章第一节中有这样一个声明:

(*(void(*)())0)();

看到这样的表达式估计让不少人都“不寒而栗”了吧,其实虽然看起来复杂,但是构造这类表达式其实只有一条简单的规则:按照使用的方式来声明。

首先先介绍一个著名的解析法则:右左法则:首先从圆括号起,然后向右看,然后向左看,每当遇到圆括号时,就调转阅读方向,当括号内的内容解析完毕,就跳出这个括号,重复这个过程直到表达式解析完毕。

其实我们发现,所谓复杂指针离不开指针函数,函数指针,指针数组,函数指针这四个概念并且括号,*比较多,其实只要我们仔细分析这些看起来复杂的表达式,其实他的逻辑也是很清晰的。

举个例子,使用右左法则解析复杂的表达式:

Int *(*(*pfun)(int *))[10];

用右左法则解析这个表达式,首先要找到未定义的标识符pfun,当往右看的时候遇到括号,于是调转方向,再朝相反的方向看,pfun遇到了*,说明pfun是一个指针,再往左看又遇到了括号,因此又要调转方向,遇到的是另外一个括号,因此说明指针所指向的是一个函数,函数的参数是一个整型指针。然后又向相反的方向看,又遇到了一个*,说明该函数的返回值又是一个指针,在往左看又遇到括号,所以再次调转方向,把内侧的括号里的内容看完,出了括号遇到的是数组,说明指针所指向的函数的返回值类型的指针指向的是数组,这有点向绕口令,但是还是有逻辑可循的。

但是右左法则确实有点麻烦,我们这样看上面这个表达式:首先fpun是一个指向函数的函数指针,该函数有一个整型指针类型的参数并且返回值也是一个指针,所返回的类型指向的是一个数组,并且这个数组有10个元素,每个元素是整型指针类型。

接下来我们在回过头来看文章最开始的那个表达式:

(*(void(*)())0)();

我们先看括号里面的内容,首先0被强制转换为一个返回值为void类型,没有参数的函数的函数指针,指针(void)(*)()0)指向了一个函数。

要想很好的解决这个问题,选择使用typedef是一个很好的方式。

C语言之复杂指针详解的更多相关文章

  1. 结构体指针,C语言结构体指针详解

    结构体指针,可细分为指向结构体变量的指针和指向结构体数组的指针. 指向结构体变量的指针 前面我们通过“结构体变量名.成员名”的方式引用结构体变量中的成员,除了这种方法之外还可以使用指针. 前面讲过,& ...

  2. 深入理解C语言 - 指针详解

    一.什么是指针 C语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每个字节有唯一的内存地址.CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位.这里,数据对象是指存储在 ...

  3. Linux C 语言之 Hello World 详解

    目录 Linux C 语言之 Hello World 详解 第一个 C 语言程序 程序运行原理 编译,链接 运行时 链接库 编译器优化 Hello World 打印原理 stdout, stdin 和 ...

  4. Delphi指针详解

    Delphi指针详解2007-12-04 06:08:57|  分类: DLL学习 阅读91 评论0   字号:大中小 订阅 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用 ...

  5. [转]C++ 智能指针详解

    转自:http://blog.csdn.net/xt_xiaotian/article/details/5714477 C++ 智能指针详解 一.简介 由于 C++ 语言没有自动内存回收机制,程序员每 ...

  6. C++ 智能指针详解(转)

    C++ 智能指针详解   一.简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete.程序员忘记 delete,流程太复杂,最终导致没有 delete,异常 ...

  7. [转]C语言字节对齐问题详解

    C语言字节对齐问题详解 转载:https://www.cnblogs.com/clover-toeic/p/3853132.html 引言 考虑下面的结构体定义: typedef struct{ ch ...

  8. 【C++】智能指针详解(一):智能指针的引入

    智能指针是C++中一种利用RAII机制(后面解释),通过对象来管理指针的一种方式. 在C++中,动态开辟的内存需要我们自己去维护,在出函数作用域或程序异常退出之前,我们必须手动释放掉它,否则的话就会引 ...

  9. C语言解决约瑟夫问题详解的代码

    将开发过程中比较重要的一些内容做个收藏,下面的内容是关于C语言解决约瑟夫问题详解的内容,希望能对码农有帮助. #pragma once #include<vector> class PRO ...

随机推荐

  1. Install WindowBuilder for Eclipse

    WindowBuilder官方下载安装说明地址:http://www.eclipse.org/windowbuilder/download.php 先祝各位能顺利安装上!以下是基于Eclipse in ...

  2. 传说中的WCF(8):玩转消息协定

    Message翻译成中文,相信各位不陌生,是啊,就是消息,在WCF中也有消息这玩意儿,不知道你怎么去理解它.反正俺的理解,就像我们互发短信一个道理,通讯的双方就是服务器与客户端,说白了吧,就是二者之间 ...

  3. Codeforces Round #337 (Div. 2) B. Vika and Squares 水题

    B. Vika and Squares   Vika has n jars with paints of distinct colors. All the jars are numbered from ...

  4. 使用var声明的变量 和 直接赋值并未声明的变量的区别

    在看JS高级程序设计时忽然想到这个问题,众所周知,直接赋值一个变量而为声明,会产生一个全局变量(或者说是全局对象的属性),但用var声明的变量 和 直接赋值而并未声明的变量 都有哪些区别呢,这是我在百 ...

  5. activity 的四种启动方式

    Activity启动模式设置: <activity android:name=".MainActivity" android:launchMode="standar ...

  6. 跨浏览器兼容的HTML5视频音频播放器

    HTML5的video和audio标签是用来在网页中加入视频和音频的标签,在支持html5的浏览器中不需要预先加载Adobe Flash浏览器插件就能轻松快速的播放视频和音频文件.而html5medi ...

  7. IOS底层数据结构--class

    一.类的数据结构 Class(指针) typedef struct objc_class *Class; /* 这是由编译器为每个类产生的数据结构,这个结构定义了一个类.这个结构是通过编译器在执行时产 ...

  8. CentOS中通过stat查看文件的元数据

    CentOS中可以通过stat查看文件的元数据 [baby@xiaoxiao abc]$ stat honey  File: `honey'  Size: 25         Blocks: 8   ...

  9. Linux系统文件权限&目录权限

    linux系统一切都是文件,文件和目录的所属与权限--来分别规定所有者.所有组.其余人的读.写.执行权限. 读(read),写(write),执行(excute)简写为(r.w.x),也可以以用(4. ...

  10. Can't find bundle for base name ClientMessages, locale zh_CN

    这是个关于JAVA国际化方面的语音包的问题. 提示这个错误信息就是说找不到代码里写的配置文件. 我这个错误发生在导入一个已经存在的项目时发生的. 解决办法:将配置文件*.properties所在的文件 ...