你怎么读C声明?

问题描述 投票:41回答:10

我听说过一些方法,但都没有卡住。我个人试图避免C中的复杂类型,并尝试将它们分解为组件typedef。

我现在面临着从一个所谓的“三星级程序员”维护一些遗留代码的问题,而且我很难阅读一些***代码[] []。

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

c typedef cdecl
10个回答
32
投票

本文解释了一个相对简单的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


0
投票

刚刚遇到“The Development of the C Language”的一个有启发性的部分:

对于这种组合类型的每个对象,已经有一种方法可以提及底层对象:索引数组,调用函数,在指针上使用间接运算符。类比推理导致了一个声明语法,用于反映名称通常出现的表达式语法的名称。从而,

int i, *pi, **ppi;

声明一个整数,一个指向整数的指针,一个指向整数指针的指针。这些声明的语法反映了在表达式中使用i,* pi和** ppi都会产生int类型的观察结果。同样的,

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

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

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

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


22
投票

我通常使用有时被称为“右手顺时针规则”的东西。它是这样的:

  • 从标识符开始。
  • 转到它的右边。
  • 然后顺时针方向移动到左侧。
  • 顺时针移动并向右移动。
  • 只要声明尚未完全解析,请执行此操作。

还有一个额外的元规则需要注意:

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

在这里,“前进”和“移动”某处意味着在那里阅读符号。规则是:

  • * - 指向
  • () - 功能返回
  • (int, int) - 功能采取两个整数并返回
  • intchar等 - intchar等。
  • [] - 数组
  • [10] - 十个阵容
  • 等等

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

xyz是一个

一排十

指针

函数接受一个int *和一个char并返回

一个int *


6
投票

一个字:cdecl

Damnit,被打15秒!


4
投票

Cdecl(和c ++ decl)是一个用于编码和解码C(或C ++)类型声明的程序。

http://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html


3
投票

回到我做C的时候,我使用了一个名为“cdecl”的程序。它似乎是在cutils或cdecl包中的Ubuntu Linux中,它可能在其他地方可用。


1
投票

还有一个很漂亮的Web-based version of cdecl


1
投票

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

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 Deep Secrets”一书中有一整章的内容,名为“在C中解读声明”。


0
投票

常见的可读性问题包括function pointersarrays are really pointers的事实,以及multidimensional arrays are really single dimension arrays (which are really pointers).希望帮助一些。

在任何情况下,每当你理解声明时,也许你可以想出一种简化它们的方法,使它们对下一个人来说更具可读性。


0
投票

自动化解决方案是cdecl。

通常,您以使用它的方式声明变量。例如,您取消引用指针p,如下所示:

char c = * p

你以类似的方式声明它:

char * p;

毛茸茸的函数指针也是如此。让我们声明f是一个很好的旧“指向函数返回指向int的指针”,并且外部声明只是为了搞笑。它是一个指向函数的指针,所以我们从:

extern * f();

它返回一个指向int的指针,所以在前面的某处就有了

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

现在哪个是正确的关联性?我永远不会记得,所以请使用一些括号。

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

以你使用它的方式声明它。

© www.soinside.com 2019 - 2024. All rights reserved.