2008-09-18 70 views
41

我听说过一些方法,但都没有卡住。就我个人而言,我尝试在C中避免复杂的类型,并尝试将它们分解为组件typedef。你如何阅读C声明?

我现在正在维护一个所谓'三星程序员'的遗留代码,而且我很难读一些***代码[] []。

您如何阅读复杂的C声明?

+2

眼睛工作......但如果你用Windows卡住了,我想你可以试试Narrator。 – Shog9 2008-09-18 01:05:24

+5

“三星级程序员”是否意味着他所宣称的所有类型中至少有三颗星? – 2008-09-18 01:06:19

+3

很多,这是一个坏的c程序员的老学校侮辱 – 1729 2008-09-18 01:08:23

回答

3

回到我在做C时,我使用了一个名为“cdecl”的程序。看起来它在Ubuntu Linux中的cutils或cdecl包中,并且可能在其他地方提供。

5

一个字:cdecl

该死,通过15秒挨打!

28

本文介绍了一种相对简单的规则7可以让你读任何C的声明,如果你发现自己想要或者需要手动执行:http://www.ericgiguere.com/articles/reading-c-declarations.html

  1. 查找标识符。这是你的出发点。在一张纸上,写上“声明标识符为”。
  2. 向右看。如果没有任何内容,或者有右括号“)”,则转到步骤4.
  3. 您现在位于数组(左括号)或函数(左括号)描述符上。可能有一系列的这些结束,无论是右括号还是结尾(分号或用于初始化的“=”)。对于每个这样的描述符,从读取从左到右:

    • 如果空数组“[]”,写入
    • “的数组”如果与尺寸的阵列,写
    • “的数组大小”如果函数“()”写“返回函数”

    停在不匹配的圆括号或者说明符的末尾,以先到者为准。

  4. 返回到开始位置并向左看。如果没有任何东西,或者有左括号“(”,转到第6步。
  5. 您现在被定位在一个指针描述符“*”上。左边可能有一个这样的序列,一个不匹配的左括号“(”或者声明符的开头,从右到左读取,为每个指针描述符写入“指向”的指针,停在不匹配的括号或声明符的开头,以先到者为准。
  6. 在这一点上,你有一个加括号的表达式或完整的声明。如果您有一个加括号的表达式,请将其视为您的新起点并返回到步骤2.
  7. 记下类型说明符。停止。

如果你很好用的工具,那么我第二个建议使用程序cdeclhttp://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html

1

CDECL提供了一个命令行界面,让我们试试看:

另一示例

explain int (*IMP)(ID,SEL) 
declare IMP as pointer to function (ID, SEL) returning int 

然而吨这里是关于书中“C深层的秘密”一整章,在C.

名为“解读声明问候 弗里德里希

20

我一般用什么有时被称为‘右手顺时针规则’。 它是这样的:

  • 从标识符开始。
  • 转到它的右侧。
  • 然后顺时针移动到左侧。
  • 顺时针方向移动到右侧。
  • 只要声明没有被完全解析,就这样做。

有有被照顾的一个额外的元规则:

  • 如果有括号,迁出前完成括号的每个级别。

在这里,'去'和'移动'的地方意味着在那里读取符号。该规则是:

  • * - 指针
  • () - 函数返回
  • (int, int) - 功能以两个整数并返回
  • intchar等 - intchar等。
  • [] - 数组
  • [10] - 十个数组

因此,举例来说,int* (*xyz[10])(int*, char)读作:

XYZ是

阵列10

指针

函数采取一个int *和炭并返回

int *

0

自动化的解决方案是的cdecl。

一般情况下,您使用它的方式声明变量。例如,取消引用指针p为:

 
char c = * p 

你在一个类似的寻找方式声明它:

 
char * p; 

也是一样的毛茸茸的函数指针。让我们声明f是很好的“指向返回指向int的函数的指针”,并且外部声明只是有趣的。这是一个指向函数的指针,所以我们先从:

 
extern * f(); 

它返回一个指向一个int,在前面,所以某个地方有还有的

 
extern int * * f(); // XXX not quite yet 

现在,这是正确的关联?我永远不会记住,所以用一些括号。

 
extern (int *)(* f)(); 

声明它的使用方式。

0

从右到左阅读。

***code[][] 
  • 代码[] []是一multidimenstional阵列
  • *代码[] []是一multidimenstional数组指针
  • **代码[] []是一multidimenstional阵列指针的指针
  • ***代码[] []是一multidimenstional阵列指针的指针的指针
0

对面照明部在“The Development of the C Language来到“:

对于这种组合类型的每个对象,已经有一种方法来提及基础对象:索引数组,调用函数,在指针上使用间接运算符。类比推理导致名称的声明语法镜像名称通常出现的表达式语法的名称。因此,

int i, *pi, **ppi;

声明的整数,一个指针到一个整数,指针的指针的整数。这些声明的语法反映了当在表达式中使用时,i,* pi和** ppi都会产生int类型。类似地,

int f(), *f(), (*f)();

声明函数返回一个整数,返回指针到一个整数的函数,一个指向函数返回的整数;

int *api[10], (*pai)[10];

声明指针数组为整数,和一个指向整数数组。在所有这些情况下,变量的声明类似于它在声明头部命名的表达式中的用法。