摘录的别人的: 



C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的。右左法则的英文原文是这样说的: 



The   right-left   rule:   Start  reading   the   declaration   from   the   innermost  parentheses,   go   right,   and   then   go  left.   When   you   encounter   parentheses,  the   direction   should   be   reversed.   Once  everything   in   the   parentheses
  has  been   parsed,   jump   out   of   it.   Continue  till   the   whole   declaration   has   been  parsed.   





这段英文的翻译如下: 



右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。 



               笔者要对这个法则进行一个小小的修正,应该是从未定义的标识符开始阅读,而不是从括号读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个。 



               现在通过一些例子来讨论右左法则的应用,先从最简单的开始,逐步加深: 



int   (*func)(int   *p); 



首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值类型是int。 



int   (*func)(int   *p,   int  (*f)(int*)); 



func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int   *和int  (*)(int*)这样的形参,返回值为int类型。再来看一看func的形参int  (*f)(int*),类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。 



int   (*func[5])(int   *p); 



func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针,要注意这里的*不是修饰func的,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合,因此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值类型为int。 





int   (*(*func)[5])(int   *p); 



func被一个圆括号包含,左边又有一个*,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int*形参,返回值为int类型的函数。 



int   (*(*func)(int   *p))[5]; 



func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。 



要注意有些复杂指针声明是非法的,例如: 



int   func(void)   [5]; 



func是一个返回值为具有5个int元素的数组的函数。但C语言的函数返回值不能为数组,这是因为如果允许函数返回值为数组,那么接收这个数组的内容的东西,也必须是一个数组,但C语言的数组名是一个右值,它不能作为左值来接收另一个数组,因此函数返回值不能为数组。 



int   func[5](void); 



func是一个具有5个元素的数组,这个数组的元素都是函数。这也是非法的,因为数组的元素除了类型必须一样外,每个元素所占用的内存空间也必须相同,显然函数是无法达到这个要求的,即使函数的类型一样,但函数所占用的空间通常是不相同的。 



作为练习,下面列几个复杂指针声明给读者自己来解析,答案放在第十章里。 



int   (*(*func)[5][6])[7][8]; 



int   (*(*(*func)(int   *))[5])(int  *); 



int   (*(*func[7][8][9])(int*))[5]; 



               实际当中,需要声明一个复杂指针时,如果把整个声明写成上面所示的形式,对程序可读性是一大损害。应该用typedef来对声明逐层分解,增强可读性,例如对于声明: 



int   (*(*func)(int   *p))[5]; 



可以这样分解: 



typedef     int   (*PARA)[5]; 

typedef   PARA   (*func)(int  *); 



这样就容易看得多了。

C指针右左法则的更多相关文章

  1. C语言 右左法则

    C指针声明解读之左右法则 C语言所有复杂的指针声明,都是由各种声明嵌套构成的.如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法.不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定 ...

  2. CSS 如何让Table的里面TD全有边框 而Table的右左边框没有

    比如这样一个CSS.td3{font-size: 14px;color: #FFFFFF;background-color: #000000;BORDER-RIGHT: #f6f6f6 1px sol ...

  3. C语言之复杂指针详解

    在<C陷阱与缺陷>第二章第一节中有这样一个声明: (*(void(*)())0)(): 看到这样的表达式估计让不少人都“不寒而栗”了吧,其实虽然看起来复杂,但是构造这类表达式其实只有一条简 ...

  4. char (*(*p[3])( int ))[5] 等等一系列 左右法则

    看这个: C指针声明解读之左右法则C语言所有复杂的指针声明,都是由各种声明嵌套构成的.如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法.不过,右左法则其实并不是C标准里面的内容,它是从C标准的 ...

  5. C语言复杂的函数指针声明

    复习C语言ING,发现复杂的函数指针声明看不懂,百度半天终于略知一二. 讲的比较详细的一篇blog: http://blog.csdn.net/megaboy/article/details/4827 ...

  6. 指针超强汇总(谨记优先级:() > [] > *)

    参考:http://blog.chinaunix.net/uid-20120277-id-5760985.html C语言所有复杂的指针声明,都是由各种声明嵌套构成的.如何解读复杂指针声明呢?右左法则 ...

  7. C语言学习笔记--指针阅读技巧

    1. 指针阅读技巧:右左法则 (1)从最里层的圆括号中未定义的标示符看起 (2)首先往右看,再往左看 (3)遇到圆括号或方括号时可以确定部分类型,并调转方向 (4)重复 2.3 步骤,直到阅读结束 注 ...

  8. C_C++指针指针应用详解

    前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其 ...

  9. C++-指针阅读能力提升

    下面的标识符你肯定在工程中看不到,但是在面试题中却非常常见,掌握掌握还是不错的. int (*p1)(int*, int (*f)(int*));              int (*p2[5])( ...

随机推荐

  1. linux(raspbian)下mysql的安装,权限设置和用户管理

    一 MySQL安装:(1) 使用apt-get安装, 由于raspbian是基于Debian的自由操作系统,debian默认自带apt-get指令安装应用因此可以使用来安装 sudo apt-get ...

  2. Q&A系列一:DataPipeline常见问题回答

    不知不觉中,大家已经陪伴DataPipeline走过了3年时间.在这期间,得益于客户们的积极反馈和沟通,我们总结了一些日常工作中比较常见的问题,并基于这些问题进行了总结. 为避免突兀,我们会先从比较基 ...

  3. JavaScript | ES6 新增

    Evernote Export body, td { font-family: 微软雅黑; font-size: 10pt; } ES6 重点知识 this关键字以及bind let/const 变量 ...

  4. Codeforces Round #609 (Div. 2)前五题题解

    Codeforces Round #609 (Div. 2)前五题题解 补题补题…… C题写挂了好几个次,最后一题看了好久题解才懂……我太迟钝了…… 然后因为longlong调了半个小时…… A.Eq ...

  5. vue vuex开发中遇到的问题及解决小技巧

    1.在vue的开发中,如果使用了vuex,数据的组装,修改时在mutations中,页面是建议修改变量值的,如果强制修改,控制台就会出现错误.如下: 这种错误虽然不会影响结果,但是是vuex不提倡的方 ...

  6. NetCore下的log4

    https://www.cnblogs.com/zhangxiaoyong/p/9463791.html 这一篇也不错 .NET常用的日志组件有NLog.Log4net等,.NET CORE下微软也自 ...

  7. java 自增/减运算符

    注意:python中没有 一.自增运算符 1.单独使用时,目的获取变量的值,前++和后++没有区别,使用后值都会递增一. 2.混合使用时,才有区别.前++,先加后用.后++,先用后加 二.自减运算符 ...

  8. SSAS Tabular表格模型实现动态权限管理

    最近忽然对SSAS产生了浓厚兴趣,我看博客园上也米有写关于SSAS 2016下表格模型实现动态权限管理的文章,最近鼓捣了一下微软的样例,鼓捣好了,把过程中遇到的一些问题写出来,抛砖引玉,也算给自己一个 ...

  9. Bootstrap File Input 的使用

    由于工作需要使用Bootstrap的FileInput插件,在此分享下插件的使用方法 直接上代码 fileinput.html <!DOCTYPE html> <html> & ...

  10. 可视化限流管理,Sentinel 控制台启动和接入

    Sentinel 的使用可以分为核心库和控制台两个部分. 核心库不依赖任何框架/库,集成了主流框架,可以进行单机限流降级等功能, 控制台Dashboard提供了可视化的管理限流规则.对集群进行监控,集 ...