我们如何阅读C声明?
我听说过一些方法,但是没有一个卡住。就我个人而言,我尝试避免在C语言中使用复杂类型,并尝试将它们分解为组件typedef。
我现在面临着维护所谓的"三星级程序员"的一些遗留代码的麻烦,而且我很难读一些*** code [] []。
我们如何阅读复杂的C声明?
解决方案
回到我做C时,我使用了一个名为" cdecl"的程序。看来它是在Ubuntu的cutils或者cdecl软件包中的Linux中,并且可能在其他地方可用。
一个词:cdecl
该死的,被打了15秒!
Cdecl(和c ++ decl)是用于编码和解码C(或者C ++)类型声明的程序。
http://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html
常见的可读性问题包括函数指针以及数组实际上是指针,而多维数组实际上是一维数组(实际上是指针)。希望对我们有所帮助。
无论如何,只要我们理解声明,就可以找到简化它们的方法,使下一个人更容易理解。
本文介绍了一个相对简单的7条规则,如果我们发现自己有需要或者需要手动阅读C声明,则可以使用它们:http://www.ericgiguere.com/articles/reading-c-declarations.html
Find the identifier. This is your starting point. On a piece of paper, write "declare identifier as". Look to the right. If there is nothing there, or there is a right parenthesis ")", goto step 4. You are now positioned either on an array (left bracket) or function (left parenthesis) descriptor. There may be a sequence of these, ending either with an unmatched right parenthesis or the end of the declarator (a semicolon or a "=" for initialization). For each such descriptor, reading from left to right: if an empty array "[]", write "array of" if an array with a size, write "array size of" if a function "()", write "function returning" Stop at the unmatched parenthesis or the end of the declarator, whichever comes first. Return to the starting position and look to the left. If there is nothing there, or there is a left parenthesis "(", goto step 6. You are now positioned on a pointer descriptor, "*". There may be a sequence of these to the left, ending either with an unmatched left parenthesis "(" or the start of the declarator. Reading from right to left, for each pointer descriptor write "pointer to". Stop at the unmatched parenthesis or the start of the declarator, whichever is first. At this point you have either a parenthesized expression or the complete declarator. If you have a parenthesized expression, consider it as your new starting point and return to step 2. Write down the type specifier. Stop.
如果我们对工具满意,那么我建议使用程序cdecl:http://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html
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中的解密声明"。
问候
弗里德里希
我通常使用有时称为"右手顺时针规则"的内容。
它是这样的:
- 从标识符开始。
- 转到它的直接右边。
- 然后顺时针移动并移至左侧。
- 顺时针移动并移至右侧。
- 只要声明没有被完全解析,就可以这样做。
还有一个添加的元规则必须注意:
- 如果有括号,请在移出前完成每个级别的括号。
在这里,"去"和"移动"到某处意味着在该处读取符号。规则是:
- *-指向的指针
()
-函数返回(int,int)
-接受两个int并返回的函数int
,char
等。-int
,char
等。[]
-的数组[10]
-十个数组- 等等。
因此,例如,int *(* xyz [10])(int *,char)
读为:
xyz is an array of ten pointer to function taking an int* and a char and returning an int*
http://eli.thegreenplace.net/2008/07/18/reading-c-type-declarations/
自动化解决方案是cdecl。
通常,我们以使用变量的方式声明变量。例如,我们取消引用指针p的方式如下:
char c = * p
我们以类似的方式声明它:
char * p;
多毛的函数指针也是如此。让我们将f声明为旧的"返回int的函数的指针",以及一个有趣的外部声明。它是一个函数的指针,因此我们从以下内容开始:
extern * f();
它返回一个指向int的指针,所以在前面的某个地方
extern int * * f(); // XXX not quite yet
现在,哪个是正确的关联性?我不记得了,所以使用一些括号。
extern (int *)(* f)();
声明使用方式。
从右到左阅读。
***code[][]
- code [] []是一个多维数组
- code [] []是多维数组指针
- ** code [] []是指向指针的多维数组指针
- *** code [] []是一个多维数组指针,指向一个指针
刚刚在" C语言的发展"中遇到了一个启发性的部分:
For each object of such a composed type, there was already a way to mention the underlying object: index the array, call the function, use the indirection operator on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus, int i, *pi, **ppi; declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression. Similarly, int f(), *f(), (*f)(); declare a function returning an integer, a function returning a pointer to an integer, a pointer to a function returning an integer; int *api[10], (*pai)[10]; declare an array of pointers to integers, and a pointer to an array of integers. In all these cases the declaration of a variable resembles its usage in an expression whose type is the one named at the head of the declaration.