2012-11-09 154 views
6

我正在閱讀'The C Programming Language',並且遇到關於typedef struct的問題。該代碼是這樣的:struct typedef中的聲明規則

typedef struct tnode *Treeptr; 
typedef struct tnode { /* the tree node: */ 
    char *word; /* points to the text */ 
    int count; /* number of occurrences */ 
    struct tnode *left; /* left child */ 
    struct tnode *right; /* right child */ 
} Treenode; 

通過我們寫

typedef struct tnode *Treeptr; 

TNODE仍尚未宣佈的時間,但我們沒有得到任何編譯錯誤, 但是當我們改變上面的語句成:

typedef Treenode *Treeptr; 

我們得到的編譯錯誤:

error: parse error before '*' token 
warning: data definition has no type or storage class 

是什麼導致差異? 「結構tnode」不是「Treenode」嗎?

+0

您可能會發現[C標準的哪個部分允許此代碼編譯?](http://stackoverflow.com/questions/12200096/which-part-of-the-c-standard-allows-this-code C++標準是否認爲這個頭文件中有一個或兩個'struct uperms_entry'類型?](http://stackoverflow.com/questions/11697705/does-the-c-standard-consider -that-one-or-two-struct-uperms-entry-typ)作爲相關內容,但它們可能會超出你所在的級別。 –

回答

6

在定義之前,您不能使用類型。

typedef struct tnode { ... } Treenode;聲明中,類型Treenode未定義,直到達到分號。

typedef struct tnode *Treeptr;的情況不同。這告訴編譯器'有一個叫做struct tnode的結構類型,而Treeptr這個類型是指向struct tnode'的指針的別名。該聲明結束時,struct tnode是不完整的類型。您可以創建指向不完整類型的指針,但不能創建不完整類型的變量(因此您可以定義Treeptr ptr1;struct tnode *ptr2;,它們是相同類型,但不能定義struct tnode node;)。

struct tnode的主體可以被寫爲:

typedef struct tnode 
{ 
    char *word; 
    int  count; 
    Treeptr left; 
    Treeptr right; 
} Treenode; 

因爲Treeptr被定義爲結構之前的類型struct tnode *已知別名。您不能使用Treenode *left;,因爲Treenode在達到最終分號(粗略地說)之前不是已知的別名。

0

typedef struct tnode *Treeptr;具有「tnode」結構的隱式前向聲明。它類似於:

typedef struct tnode Treenode; 
typedef Treenode *Treeptr; 

struct tnode { /* the tree node: */ 
    char *word; /* points to the text */ 
    int count; /* number of occurrences */ 
    struct tnode *left; /* left child */ 
    struct tnode *right; /* right child */ 
}; 
1

當您聲明TreePtr時,您沒有實現該結構。這就是所謂的「正向聲明」。類似於:「我們在這裏使用這個,但稍後我會更好地解釋它」。該實現必須稍後纔會出現,只有一次,這就是您在第二個typedef中找到的內容。

TreePtr與結構不一樣,因爲TreePtr實際上是一個新的類型,它包含了一個指針指向的事實。

+0

謝謝,Fèlix,很好的解釋。所以你的意思是'struct undefined_struct * a;'是允許的,但是在我們說'struct undefined_struct b'之前我們應該實現'undefined_struct',是嗎?但是這個「_foward declaration_」的意圖是什麼? – Rain

+1

前向聲明,或不完整的類型在兩種情況下可能會有所幫助,可以創建相互遞歸的結構,以便'struct a'包含一個指向'struct b'的指針,'struct b'包含一個指向'struct a'的指針。這是很深奧的(但是如果不能進行前向聲明,這將是一個真正的問題)。不完整類型的更多原因是你可以根據指向不完整類型的指針定義接口到一組函數,並且公共頭文件不需要揭示結構中的內容;它們是一種「不透明類型」,並且您正在使用信息隱藏功能 –

+0

您可以按照任意組合執行諸如「struct undef a;」,「struct undef * b;」等操作,如就像你需要的一樣,你可以包括將它們放在另一個結構中。但是你必須在你喜歡的地方和時間聲明結構的實現。 –