簡體   English   中英

你如何閱讀 C 聲明?

[英]How do you read C declarations?

我聽說過一些方法,但沒有一個被卡住。 就我個人而言,我盡量避免在 C 中使用復雜類型,並嘗試將它們分解為組件 typedef。

我現在面臨着維護所謂的“三星級程序員”的一些遺留代碼的問題,而且我很難閱讀一些 ***code[][]。

你如何閱讀復雜的 C 聲明?

這篇文章解釋了一個相對簡單的 7 條規則,如果您發現自己想要或需要手動閱讀任何 C 聲明,它可以讓您閱讀:http ://www.ericgiguere.com/articles/reading-c-declarations.html

  1. 找到標識符。 這是你的起點。 在一張紙上,寫上“declare identifier as”。
  2. 向右看。 如果那里什么都沒有,或者有一個右括號“)”,則轉到步驟 4。
  3. 您現在位於數組(左括號)或函數(左括號)描述符上。 可能有一系列這些,以不匹配的右括號或聲明符的結尾(分號或“=”表示初始化)結束。 對於每個這樣的描述符,從左到右閱讀:

    • 如果一個空數組“[]”,寫“數組”
    • 如果數組的大小,寫“數組大小”
    • 如果是函數“()”,則寫“函數返回”

    停在不匹配的括號或聲明符的末尾,以先到者為准。

  4. 回到起始位置,向左看。 如果那里什么都沒有,或者有一個左括號“(”,請轉到步驟 6。
  5. 您現在位於指針描述符“*”上。 左邊可能有這些序列,以不匹配的左括號“(”或聲明符的開頭結尾。從右到左讀取,為每個指針描述符寫入“指向”。在不匹配的括號處停止或聲明符的開始,以先到者為准。
  6. 此時,您有一個帶括號的表達式或完整的聲明符。 如果您有一個帶括號的表達式,請將其視為新的起點並返回到第 2 步。
  7. 寫下類型說明符。 停止。

如果您對工具沒問題,那么我建議使用cdecl程序: http : cdecl

我通常使用有時稱為“右手順時針規則”的方法。 它是這樣的:

  • 從標識符開始。
  • 轉到它的右側。
  • 然后順時針移動並來到左側。
  • 順時針移動並來到右側。
  • 只要聲明尚未完全解析,就執行此操作。

還有一個額外的元規則需要注意:

  • 如果有括號,請在搬出之前完成每一級括號。

在這里,“去”和“移動”某處意味着閱讀那里的符號。 規則是:

  • * - 指向
  • () - 函數返回
  • (int, int) - 函數取兩個整數並返回
  • intchar等 - intchar
  • [] - 數組
  • [10] - 十個數組
  • 等等。

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

xyz 是一個

十個數組

指向

函數接受一個 int* 和一個字符並返回

一個整數*

一個字: cdecl

媽的,被打了15秒!

Cdecl(和 c++decl)是一個用於編碼和解碼 C(或 C++)類型聲明的程序。

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

當我在做 C 時,我使用了一個名為“cdecl”的程序。 它似乎在 Ubuntu Linux 中的 cutils 或 cdecl 包中,並且可能在其他地方可用。

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”一書中有一整章,名為“Unscrambled Declarations in C.

還有一個基於 Web 的 cdecl 版本,它非常漂亮。

自動化解決方案是 cdecl。

通常,您可以按照使用變量的方式聲明變量。 例如,您將指針 p 取消引用,如下所示:

char c = * p

你以類似的方式聲明它:

char * p;

毛茸茸的函數指針也是如此。 讓我們將 f 聲明為舊的“指向函數的指針,返回指向 int 的指針”,並聲明一個外部聲明只是為了好玩。 它是一個指向函數的指針,所以我們開始:

extern * f();

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

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

現在哪個是正確的結合性? 我不記得了,所以用一些括號。

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

以您使用它的方式聲明它。

剛剛在“ C 語言的發展”中看到了一個有啟發性的部分:

對於這種組合類型的每個對象,已經有一種方法可以提及底層對象:索引數組、調用函數、在指針上使用間接運算符。 類比推理導致名稱的聲明語法與名稱通常出現的表達式語法的聲明語法相同。 因此,

int i, *pi, **ppi;

聲明一個整數,一個指向整數的指針,一個指向整數指針的指針。 這些聲明的語法反映了當在表達式中使用時 i、*pi 和 **ppi 都產生 int 類型的觀察結果。 相似地,

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

聲明一個返回整數的函數,一個返回整數指針的函數,一個返回整數的函數指針;

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

聲明一個指向整數的指針數組,以及一個指向整數數組的指針。 在所有這些情況下,變量的聲明類似於它在表達式中的用法,該表達式的類型是在聲明開頭命名的類型。

常見的可讀性問題包括函數指針以及數組實際上是指針以及多維數組實際上是單維數組(實際上是指針)這一事實 希望能幫到一些人。

在任何情況下,只要你理解了這些聲明,也許你就可以想出一種方法來簡化它們,使它們對下一個人來說更具可讀性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM