`
michael-java
  • 浏览: 18850 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
最近访客 更多访客>>
社区版块
存档分类
最新评论

第八章 右左法则----复杂指针解析

阅读更多

 

上一章费那么多唇舌讨论C语言的声明,其实目的都是为了这一章,期望读者通过对C语言声明形式的详细了解,树立声明嵌套的观念,因为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指针示例分析(超全面)

    对于更复杂的指针声明,我们可以通过所谓的“右左法则”来进行解析。该法则的核心在于按照一定的顺序逐步解析声明中的每一部分。具体步骤如下: - **右左法则**: - 从最内部的括号开始阅读。 - 首先向右读,然后...

    超强的C语言指针学习笔记.pdf

    右左法则是一种用于解析复杂指针声明的有效方法。其核心思想是从最内层的圆括号开始,按照一定的顺序解析整个声明。 1. **步骤解析**: - **步骤1**:从最内侧的圆括号开始读。 - **步骤2**:向右读,遇到圆括号...

    2019 CSP-J 第一轮 答案解析.pdf

    ### 2019 CSP-J 第一轮答案解析 #### 基础概念及知识点梳理 - **中国顶级域名**: 在互联网领域中,每个国家或地区都有自己的顶级域名,中国的顶级域名为`.cn`。这是互联网地址系统的一部分,用于标识网络上的资源...

    再再论指针

    #### 八、右左法则——复杂指针解析 右左法则是理解和解释复杂指针声明的有效方法。 **原则**: - 从右向左解析指针声明。 - 首先确定基本数据类型,然后逐步分析指针类型。 **示例**: - `int *ptr[M][N];` ...

    再再论指针,指针的深入分析

    #### 八、右左法则——复杂指针解析 解析复杂的指针声明时,遵循“右左法则”可以帮助理解其含义。这个法则是指从声明的右侧开始,逐层解析,直到遇到指针符号`*`。例如,对于`int ***ptr;`,从右侧开始依次解读为...

    数组和指针的艺术,就是艺术!

    第九章的“右左法则”是解析复杂指针表达式的一种方法,通过从右到左依次计算表达式的含义,可以更容易地理解多级指针和指针运算。 最后,第十章“动态数组”讨论了使用`malloc`、`calloc`、`realloc`和`free`等...

    数据结构与算法(Java版-英文)

    - **第8章:二叉树** - 详细介绍二叉树的定义、性质、遍历方法以及平衡二叉树的概念。 - **第9章:红黑树** - 聚焦于红黑树这种自平衡的二叉查找树,探讨其插入、删除操作以及维护平衡的方法。 - **第10章:2-3-4树...

    新课标2020高中物理第四章电磁感应第3节楞次定律达标精练含解析新人教版选修3_2

    以上知识点是针对高中物理第四章电磁感应第3节楞次定律的相关内容,涉及了楞次定律的应用、感应电流的方向判断、安培力的理解以及实际问题中的应用分析。这些知识点是学习电磁感应现象和解决相关问题的基础。

    03年安大数据结构试卷

    - **解析**:森林转换为二叉树的基本方法是:森林中的第一棵树不变,其他树都作为前一棵树的最右边孩子的右孩子,同时每棵树内部按照先左后右的顺序进行连接。 **3. 对下面数据表,写出采用快速排序的每一趟的结果...

    福建省泉州市安溪县2015届九年级上期末数学试卷及答案解析.doc

    - 填空题第8题要求**二次根式有意义**,即分母不为零,所以x的取值范围是x≥0。 - 第9题涉及到**判别式**,因为一元二次方程有实数根,所以判别式Δ=b²-4ac≥0,从而得到a的取值范围。 - 第10题是**一元二次方程...

    误差理论与数据处理 第五版 1~3章答案

    #### 第一章知识点解析 **1.1 测量误差的概念** 本章节通过具体的例题深入浅出地介绍了测量误差的基本概念,包括绝对误差和相对误差。绝对误差是指测量结果与真实值之间的差值;而相对误差则是绝对误差与真实值的...

    (四川专版)2014高考物理 课时跟踪训练 第1部分 第二章 第3节 电阻的串联、并联及其应用(含解析) 新人教版选修3-1

    在第8题中,改装的电流表串联或并联连接,会影响其显示的电流值和指针偏转角度。 8. **电阻比例**:第5题通过电压分配比例计算了电阻之间的比例关系,利用电压与电阻的关系求解。 9. **误差分析**:在测量电阻时,...

    高级C语言 学完C语言来看这个绝对收获

    右左法则-复杂指针解析 解析复杂指针时,可以采用“从右向左”的法则来帮助理解。 #### 36. 回车和换行的区别 在不同的操作系统中,回车和换行有不同的表示方式。 #### 37. 堆和堆栈的区别 - **堆**:动态分配...

    2019_2020学年高中物理第二章恒定电流4串联电路和并联电路课后检测含解析新人教版选修3_1

    【知识点详解】 1. **串联电路的基本特性** - 在串联电路中,电流处处相等,即I=I1=I2=...=In。...掌握这些知识能帮助我们分析和解决实际电路问题,并进一步拓展到更复杂的电子系统和电力工程领域。

    MoreEffectiveC++

    根据给定文件的信息,我们可以将《More Effective C++》这本书中的关键知识点进行详细的解析与总结。本书主要聚焦于提升C++编程效率与质量的最佳实践,通过具体的指导原则帮助开发者更好地理解和应用C++语言特性。 ...

    2021-2022计算机二级等级考试试题及答案No.3874.docx

    ### 计算机二级等级考试知识点解析 #### 1. Access数据库表中的字段定义有效性规则 - **知识点**: 在Access数据库中,为了确保数据的有效性和一致性,可以通过定义字段的有效性规则来实现。有效性规则通常是一种...

Global site tag (gtag.js) - Google Analytics