我听说过一些方法,但都不是很实用。个人尽量避免在C语言中使用复杂数据类型,而是将其分解成组件typedef。
现在我需要维护一些所谓的“三星程序员”编写的遗留代码,我很难阅读其中一些 ***code[][].
你如何阅读复杂的C语言声明?
本文介绍了一个相对简单的7条规则,可以帮助你手动阅读任何C语言声明:
http://www.ericgiguere.com/articles/reading-c-declarations.html
如果你觉得这个工具不错,那么我支持使用程序
- 找到标识符。这是你的起点。在一张纸上写下“声明标识符为”。
- 向右看。如果那里什么也没有,或者出现了右括号“)”,则转到步骤4。
现在你所在的位置要么是数组(左方括号),要么是函数(左圆括号)描述符。可能会有一系列这些描述符,以未匹配的右括号或声明符的结尾(分号或“=”用于初始化)结束。对于从左到右阅读的每个这样的描述符:
- 如果是空数组“[]”,写下“数组”
- 如果是带有大小的数组,写下“数组大小为”
- 如果是函数“()”,写下“返回函数”
停在未匹配的括号或声明符的末尾,以先到达的为准。
- 回到起始位置并向左看。如果那里什么也没有,或者出现了左括号“(”,则转到步骤6。
- 现在你所在的位置是指针描述符“*”。可能会有一系列这些描述符在左侧,以未匹配的左括号“(”或声明符的起点结束。从右到左阅读,对于每个指针描述符,写下“指向”的字样。停在未匹配的括号或声明符的起点,以先到达的为准。
- 此时你要么有一个带括号的表达式,要么有完整的声明符。如果你有一个带括号的表达式,则将其视为新的起点,并返回步骤2。
- 写下类型说明符。结束。
cdecl
: http://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html。cdecl
的实现,甚至在K&R书中也有一个。但是它们都只是将其翻译成/从普通英语翻译而来。然而,我想要将其翻译成/从内部表示形式,就像编译器所做的那样。我的意思是,读取C声明,并将其“编码”为某种数据结构。哪种数据结构需要表示任何C声明? - cesss通常我使用右手顺时针法则,也称为“右手螺旋法则”。
还有一个要注意的额外元规则:
在这里,“前进”和“移动”意味着读取那里的符号。其规则如下:
*
- 指向()
- 返回函数(int, int)
- 接受两个int并返回函数int
, char
等- int
、char
等[]
- 数组的[10]
- 十个数组的因此,例如,int* (*xyz[10])(int*, char)
被读作:
xyz是一个
十个数组的
指向
接受int*和char并返回
int*的函数
extern char *const (*goop( char *b ))( int, long );
呢?(选自http://www.ericgiguere.com/articles/reading-c-declarations.html) - Lazer一个词: cdecl
该死,被击败了15秒!
***code[][]
,它会返回 语法错误
:-) 尽管如此,这是一个非常有用的网站。 - Mawg says reinstate Monicacdecl提供了一个命令行界面,让我们来试试:
cdecl> explain int ***c[][]
declare c as array of array of pointer to pointer to pointer to int
另一个例子
explain int (*IMP)(ID,SEL)
declare IMP as pointer to function (ID, SEL) returning int
然而,在书籍《C语言深入秘密》中有一个完整的章节专门讲解这个问题,名为“解析C语言声明”。
我曾经在做C语言时使用过一个叫做“cdecl”的程序。这个程序似乎在Ubuntu Linux的cutils或者cdecl软件包中,并且很可能也可以在其他地方找到。
我刚在 "C语言的发展" 中看到了一个启发性的章节:
对于这种组合类型的每个对象,已经有一种方法来提及底层对象:索引数组、调用函数、在指针上使用间接操作符。类比推理导致了一个声明语法,用于反映名称的表达式语法,其中名称通常出现。因此,自动化解决方案是cdecl。
通常,您声明变量的方式与使用它的方式相同。例如,您可以像这样取消引用指针p:
char c = * p
您可以以类似的方式声明它:
char * p;
对于复杂的函数指针也是如此。让我们声明f为“指向返回指针的函数”的好老朋友,并进行外部声明,只是为了好玩。由于它是一个函数指针,因此我们从以下内容开始:
extern * f();
它返回一个指向int的指针,因此在前面有:
extern int * * f(); // XXX not quite yet
现在哪个是正确的结合性?我总是记不住,所以使用一些括号。
extern (int *)(* f)();
以使用它的方式声明它。
***code[][]
,它会返回语法错误
:-) 尽管如此,这是一个非常有用的网站。 - Mawg says reinstate Monica