您的位置:首页 > 其它

如何读懂复杂的C声明

2008-08-10 15:20 225 查看
如何读懂复杂的C声明

K&R曾经承认:“C语言声明的语法有时会带来严重的问题”。的确,诸如 char * const * ( * next ) ( ) ; char * ( * c[10]) ( int ** p );之类的声明晦涩难懂,让人迷茫。还好,Peter Van Der Linden在它的经典著作《Expert C Programming》中介绍了两种解开这个难题的方法。

下面介绍读懂C语言声明两法:

一、优先级法。

A 声明从它的名字开始读取,然后按照优先级顺序依次读取。

B 优先级从高到低依次是:

B. 1 声明中被括号括起来的部分

B. 2 后缀操作符:

括号 () 表示这是一个函数

方括号 [] 表示这是一个数组

B. 3 前缀操作符:星号 * 表示 “指向...的指针”

C 如果const和(或)volatile关键字的后面紧跟类型说明符(如int,long等),那么它作用于类型说明符。在其他情况下,const和(或)volatile关键字作用于它左边紧邻的指针星号。

举例说明此法: char * const * (*next)();

A 首先,看变量名next,并注意到它直接被括号所括住

B.1 所以先把括号里的东西看为一个整体,得出“next是一个指向...的指针”

B 然后考虑括号外的东西,在星号前缀和括号后缀之间做出选择

B.2 B.2规则告诉我们优先级较高的是右边的函数括号,所以得出“next是一个函数指针,指向一个返回...的函数”

B.3 然后,处理前缀*,得出指针所指的内容

C 最后,把 char * const 解释为指向字符的常量指针

概括分析之后,这个声明表示:“next是一个指针,它指向一个函数,该函数返回另一个指针,该指针指向一个类型为char的常量指针”。

二、符号法。

步骤如下:

1、取最左边的标识符。

2、查看标识符右边的下一个符号,如果是方括号 [ ,则对于每一对,表示“...的数组”

3、如果是左括号(,则到右括号为止的内容表示“返回...的函数”

4、如果左边的符号是一个左括号(,这个括号把已经处理的部分声明组合在一起,直到遇见对应的右括号。然后从第2步重新开始。

5、如果左边的符号是下述之一:

const volatile *

继续向左读取符号,知道所读符号不再是上边那三个之一。如果符号是const,表示“只读”,如果是volatile表示“volatile”,如果是*,表示“指向...的指针”然后重复第4步。

6、剩下的符号形成声明的基本类型,剩余的符号一并阅读,如 static unsigned int

举例说明此法:char * (* c[10] ) (int **p);

剩余的声明 所采取的下一步骤 结果

char * (* c[10])(int **p) 第1步 表示“c是...”

char * (* [10])(int **p) 第2步 匹配,表示“c是...的数组”转下一步

char * (* )(int **p) 第3、4步 不匹配,转到下一步

char * (* )(int **p) 第5步 与星号匹配,表示“指向...的指针”,转第4步

char * ( )(int **p) 第4步 与“(”匹配,转到第2步

char * (int **p) 第2步 不匹配,转下一步

char * (int **p) 第3步 匹配,表示“返回...的函数,这个函数以int **p为参数”

char * 第4步 不匹配,下一步

char * 第5步 匹配,表示“指向...的指针”,剩下char,执行第6步

char 第6步 直接阅读

拼在一起,读作:“c是一个数组,它的元素是指向函数的指针,该函数以int **p为参数,返回指向char的指针”。大功告成了!

事实上,以上的解析过程完全可以写成一个程序,用来解析C声明,比如unix中的cdecl。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: