2016-10-13 76 views
-1

我試過和提煉下面的代碼儘可能:C結構的typedef和聲明造成指針錯誤

#include <stdlib.h> 

typedef struct item{ 
    struct item *next; 
}item; 

void addItem(item *list) 
{ 
    item *newItem = list; 
    while(newItem->next != NULL){ 
     newItem = newItem->next; 
    } 

    newItem->next = malloc(sizeof(item)); 
    newItem->next->next = NULL; 
} 

int main() 
{ 
    item *groceryList = NULL; 
    groceryList = malloc(sizeof(item)); 
    if(groceryList == NULL) 
     return 1; 
    groceryList->next = NULL; 

    addItem(groceryList); 

    return 0; 
} 

編譯沒有問題。但改變結構聲明(或變化的任意組合):

structpointertest.c:11:11: warning: assignment from incompatible pointer type structpointertest.c:15:15: error: request for member 'next' in something not a structure or union

我不明白,在結構聲明是什麼原因造成這個問題:編譯時

typedef struct{ /*Removed "item"*/ 
    item *next; /*Removed "struct"*/ 
}item; 

導致下列錯誤?它是否與我使用嵌套結構的事實有關?

謝謝。

+1

編譯器不知道'item'是在聲明行'item * next'處。 –

+0

沒有「嵌套結構」。不可能沒有無盡的遞歸。 – Olaf

+0

對不起,我措辭不好。我不是指嵌套結構,而是嵌套別名。 –

回答

3

在C中,您必須先聲明一些事情,然後才能使用它們。當你做

typedef struct item { ... } 

struct item部分是一個聲明,告訴存在一個結構名item編譯器。這意味着您可以稍後使用它,即使在結構中也可以定義一個指向它自己的指針。

當你

typedef struct { ... } item; 

你不給結構的名稱和類型的別名item聲明結構後,所以它不能在結構內部使用。

簡單的解決方案是使用第一種方法。另一種解決方案是結構之前申報類型的別名,如

typedef struct item item; 
struct item 
{ 
    item *next; // Can use type-alias, as it has been declared up above 
}; 

不管怎樣,你還是必須給結構本身的名稱。

還要注意的是struct item *next;(或item *next;)聲明瞭一個成員變量,它是一個指針該結構,它不是實際結構本身遞歸嵌套。創建一個指向尚未完全定義的指針是可以的。

+0

你的最後一段對我來說是不好的措辭。 –

+0

Gah,對該網站添加了新內容,在評論中輸入糟糕!無論如何,謝謝。現在我看到了typedef定義的順序。 –

+0

+1,因爲我試圖創建一個指向尚未完全定義的指針......並且令人驚訝的是它的工作原理!我不知道 – JoulinRouge