上一章费那么多唇舌讨论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 *);
这样就容易看得多了。
发表评论
-
《再再论指针》后记
2011-03-02 11:25 650在这篇后记中,笔者将对三个问题进行补充: 一、 ... -
再再论指针----篇首语
2011-03-02 11:24 563指针是C语言规范 ... -
第十章 围绕p()与(*p)()的争论
2011-03-02 11:23 684对于一个函数: void func(void) ... -
第九章 指针与const
2011-03-02 11:22 664const一词是英文constan ... -
第七章 C语言声明详解
2011-03-02 11:21 675人们常说,C语言的 ... -
第六章 “另类”数组
2011-03-02 11:20 772动态数组与字符串常量可算是两种“另类”数组。 ... -
第五章 指向数组的指针
2011-03-02 11:19 1069讲到第五章了,数组两个字还离不开我们的左右,数组的内容 ... -
第四章 [ ]运算符的本质
2011-03-02 11:18 724数组是存在于人们头 ... -
第三章 数组的解剖学
2011-03-02 11:17 584这一章我们来讨论 ... -
第二章 再一次吃惊----数组的数组与多维数组的区别
2011-03-02 11:17 494看见这个题目,也许有些人就会嘀咕了:难道两者不是一样的 ... -
第一章 什么是数组名?----一个让你吃惊的事实!
2011-03-02 11:15 707数组是指针的基础,多数人就是从数组的学习开始指针的旅程的 ... -
图书推荐
2011-02-19 19:04 793图书收藏夹 ...
相关推荐
C语言右左法则----复杂指针解析 因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既着名又常用的方法。不过,右左法 则其实并不是C标准里面的内容,它是从C标准...
右左法则是一个既著名又常用的方法。不过,右左 法则其实并不是C标 准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩 识一个声明的,...
右左法则是一个既著名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,...
第8章 善于利用指针8.1 指针是什么8.2 指针变量8.3 通过指针引用数组8.4 通过指针引用字符串8.5 指向函数的指针8.6 返回指针值的函数8.7 指
鼠标指针-蓝色鼠标指针-蓝色鼠标指针-蓝色鼠标指针-蓝色鼠标指针-蓝色鼠标指针-蓝色鼠标指针-蓝色鼠标指针-蓝色鼠标指针-蓝色鼠标指针-蓝色鼠标指针-蓝色鼠标指针-蓝色鼠标指针-蓝色
如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法
第8章 指针——函数指针的典型应用:计算定积分C语言程序设计第8章 指针如果不用函数指针编程…梯形法计算函数的定积分n为区间等分数C语言程序设计第8章 指针计算
第8章 指针——函数指针的典型应用:通用排序C语言程序设计第8章 指针如果不使用函数指针编程…编程实现升序和降序排序//选择法升序排序void Ascendin
鼠标指针-白色鼠标指针-白色鼠标指针-白色鼠标指针-白色鼠标指针-白色
第8章 指针——指针变量做函数参数:典型实例C语言程序设计第8章 指针{}{}{}{}实参形参一个典型实例——两数互换程序 1:基本类型变量作函数参数程序 2:
右左法则是一个既著名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,...
c语言程序设计教学资料第9章---指针.ppt
声明了一个函数名为f、返回值是整型指针类型的函数忘了写后一个()定义了一个整型指针变量C语言程序设计第8章 指针{}{}函数指针有什么用?{}{}C语言程序设计
第8章 指针——指针变量做函数参数C语言程序设计第8章 指针指针变量的解引用间接寻址运算符此*非彼*0{return 0;}1为什么要用指针?只要pa指向a,*
第8章 指针——指针变量做函数参数:错误案例分析C语言程序设计第8章 指针计算最高分及其学号void FindMax(int score[],long num
C语言程序设计第8章-指针.ppt
第8章 指针——字符数组与字符指针:字符串的输入和输出C语言程序设计第8章 指针{}一般不用字符串长度控制,如i逐个字符输入输出字符串C语言程序
c语言程序设计教学资料第11章---指针与数组.ppt