怎麼理解C語言的複雜聲明?


cdecl: C gibberish ? English


char (*(*X())[]) ()

X是一個函數,返回值是一個指針,該指針指向一個數組,數組裡的元素是函數指針,這些函數指針所指向的函數的返回值是char類型。

char (*(*X[3])())[5]

X是一個3個元素的數組,數組裡的元素是函數指針,這些函數指針所指向的函數的返回值也是指針,該指針指向一個有5個char類型元素的數組。


C語言指針的複雜類型說明

這是我在CSDN上的一篇文章 不敢賣弄 希望能夠解決你的問題


從未知量開始,一直推理到已知量。

例子1:char (*comp)()

  1. (*comp)

    comp解引用,這說明comp是個指針

  2. (*comp)()

    comp解引用後調用,這說明comp是個函數指針

  3. char (*comp)()

    comp解引用後調用的返回值是char,這說明comp是個返回值為char的函數指針

例子2:char (*(*X())[]) ()

  1. X()

    X調用,這說明X是個函數

  2. (*X())

    X調用的返回值解引用,這說明X是個返回值為指針的函數
  3. 現在X是什麼已經清楚了,現在的關鍵是其返回值的類型(用P表示)。

  4. (*X())[]

    P解引用後可以用[]運算,這說明P解引用後還是個指針

  5. (*(*X())[])

    P解引用後用[]運算之後的值還可以用*運算,這說明P解引用後再解引用還是個指針
  6. (*(*X())[]) ()

    P解引用後用[]運算之後再用*運算後可以調用,這說明P三次解引用後是一個函數

  7. char (*(*X())[]) ()

    該函數返回一個char
  8. 總結: X是個返回值為指針的函數,該指針解引用三次後是一個返回值為char的函數。


很多人認為 C 的類型聲明不直觀,然而如果不直觀為什麼 KR 要如此設計?

實際上 C 的聲明其實很好理解的:

char (*(*X[3])())[5]

的含義就是:「(*(*X[3-1])())[5-1]」 的類型是 char。

或者說,變數聲明

T E&

的含義是把有關變數 x 的表達式 E 的類型聲明為 T。


腦力激蕩下可以,實際中誰要是寫出來這種你可以使勁扇他。


完全應當這樣:

typedef char* (*func_t) ();
typedef func_t** (*func2_t) ();


Clockwise/Spiral Rule

不知道有沒有中文翻譯……


題主知道&不? 就是C老爹寫的那本.

在5.12節,

複雜聲明中有講解的.

  1. 解釋了怎麼讀

  2. 直接放大招, 做了一個 @坡下碎石 所說的那個網站的功能. dcl

  3. 大招裡面還有個叫undcl. 看名字就應該猜到了


Source: Reading C type declarations

如果讀C類型聲明可以理解為漸進演算法的話:

輸入: C語言的類型聲明, 例如: int **pi[5];

輸出: 英文的C類型聲明解釋(由於語言語言, 中文讀C類型聲明非常不友好), 例如: pi is an Array of 5 Pointer to Pointer to int.

演算法: (過於抽象的話, 後面有例子...)

I. 首先記住下面的規則:

i. 一個聲明&>&>必須&<&<擁有一個基本類型(basic type), 這個基本類型&>&>總是&<&<在類型聲明表達式的最左邊. 然而一個聲明可以具有&>&>0或更多&<&<個導出類型(derived type). (基本類型表請參照源鏈接)

ii. 導出類型由三個操作符(operator)構建:

i). *: 譯為 pointer to, 切記介詞to不可省略.

ii). [x]: 譯為 array of, 切記介詞of不可省略. (e.g. int ai[5]: ai is array of 5 int)

iii). ( ): 譯為 function returning. 這裡的小括弧(parentheses)指的是構成函數指針的小括弧而不是規定優先順序的小括弧. 區別: 構成函數指針的小括弧永遠出現在變數名的右邊,而規定優先順序的小括弧永遠將變數名包在裡面.

iv). ii)中的三個操作符的優先順序為: [x] 和( ) 優於*.

II. 首先由變數名以及處於最左邊的基本類型構成不完整的解釋. 然後從變數名開始由內向外解釋聲明, 遵從"能向右解讀就向右解讀, 必須向左解讀時再向左解讀".

Example: 就用提問里第二個 char (*(*x( ))[ ]) ( ); 解釋上面的演算法:

Step 1: (首先由變數名以及處於最左邊的基本類型構成不完整的解釋.): x is ... char. 下面逐步在"..."處增添關於x的解釋.

Step 2: (由於( ) 的優先順序高於*, 向右解讀): x( ): x is a function returning ... char.

Step 3: (遇到右括弧, 向左解讀): *x( ): x is a function returning pointer to ... char.

Step 4: (由於[ ] 優先順序高於*, 向右解讀): (*x( ))[ ]: x is a function returning pointer to array of ... char.

Step 5: (遇到右括弧, 向左解讀): *(*x( ))[ ]: x is a function returning pointer to array of pointers to ... char.

Step 6: (最後的右邊的括弧): (*(*x( ))[ ]) ( ): x is a function returning pointer to array of pointers to function returning char.

結果和cdecl的輸出一致.

原文圖文並茂還寫了很多其他的注意事項...


個人覺得沒意義。大牛秀智商?反被聰明誤吧。

代碼就是為了簡化得人易理解,或者說在合作中更高效率理解別人的代碼。

只是實現邏輯複雜沒辦法最簡也這麼複雜。


3,這是3個元素數組,裡面放的是指針,指針的類型一個函數(指針),這個函數的參數為空,返回值一個指針,指向5個char元素的數組!


推薦閱讀:

C語言中的指針為什麼要區別出指向不同數據類型的指針?
怎樣判斷浮點數是否相等並保證同一性?
對於一個很複雜的常量表達式,編譯器會算出結果再編譯嗎?
面向對象和面向過程分別是什麼?
C C++ Python哪個更適合新手?

TAG:編程語言 | C編程語言 | CC | 編程入門 |