[英]Why are typedef names used twice in struct declaration in C?
在研究C中的隊列時,我遇到了類似於下面的示例。 為什么結構在大括號的開頭和之后都命名? 為什么在添加相同類型的項時,結構類型在結構內部再次使用? 這些事情是多余的還是有意義的?
typedef void* vpoint_t;
typedef struct queue_item_t{
vpoint_t void_item;
struct queue_item_t* next;
} queue_item_t;
typedef struct queue_item_t { // 1
vpoint_t void_item;
struct queue_item_t* next; // 2
} queue_item_t; // 3
首先,請注意整個語句定義了一個typedef
。
3)說我們正在定義的新類型(通過typedef
) 將被命名為queue_item_t
。
1)結構的名稱(在我們去的時候給出一個新名稱)被命名為struct queue_item_t
。 這是它的全名,包括前面的struct
。
2)因為新類型還不存在(記住,我們仍然在定義它),我們必須使用它迄今為止唯一的名稱,即struct queue_item_t
,來自1) 。
請注意,您可以使用匿名struct
定義 ,這樣可以省略1)中的名稱。 一個簡單的例子:
typedef struct {
int x, y, z;
} vector3;
但是,在您的示例中,由於我們需要結構能夠引用自身,因此next
指針必須具有已定義的類型。 我們可以通過前面聲明 struct,typedefing然后使用typedef
d類型為next
定義struct來做到這一點:
struct _queue_item; // 4
typedef struct _queue_item queue_item_t; // 5
struct _queue_item { // 6
vpoint_t void_item;
queue_item_t* next; // 7
}
4)聲明struct _queue_item
存在,但尚未提供它的定義。
5) queue_item_t
與struct _queue_item
相同。
6)現在給出結構的定義......
7)......用我們typedef
“d queue_item_t
。
所有這一切......在我看來, 請不要使用typedef作為結構 。
struct queue_item {
void *data;
struct queue_item *next;
}
簡單而完整。 您可以設法鍵入這六個額外的字符。
從Linux內核編碼風格 :
第5章:Typedef
請不要使用“vps_t”之類的東西。 將typedef用於結構和指針是錯誤的 。 當你看到一個
vps_t a;
在源頭,這是什么意思? 相反,如果它說
struct virtual_container *a;
你實際上可以告訴“a”是什么。
有一些例外情況,您可以閱讀。
最近的一些相關問題:
讓我們稍微改變一下聲明,使討論更容易理解:
typedef struct queue_item {
vpoint_t void_item;
struct queue_item* next;
} QueueItemType;
C支持幾個不同的名稱空間 ; 聯合,結構和枚舉類型上的標記名稱保留一個名稱空間。 在這種情況下,標記名稱為queue_item
。 另一個名稱空間保留給常規標識符,包括typedef名稱,如QueueItemType
。
next
成員用於指向struct queue_item
類型的另一個實例(即隊列中的下一個項目)。 它被聲明為struct queue_item
的指針,原因有兩個:
結構類型不能包含自身的實例 ; 首先,類型必須是無限大的( struct queue_item
包含一個成員next
,這是一個struct queue_item
,其中包含一個成員next
,這是一個struct queue_item
,其中包含一個成員next
, ad infinitum );
結構類型定義在結束}
之前是不完整的,並且您不能聲明不完整類型的實例 。 但是,您可以聲明指向不完整類型的指針 ,我們將在下面執行此操作:
struct queue_item * next;
為什么不使用QueueItemType *next;
而不是struct queue_item *next
? 同樣,結構類型定義在聲明next
點時不完整 ; typedef名稱QueueItemType
尚不存在。 但是,標記名稱queue_item
對編譯器已經可見,因此我們可以使用struct queue_item
類型聲明指針。
由於標記名稱和typedef名稱占用不同的名稱空間,因此可以對標記名稱和typedef名稱使用相同的名稱而不會發生沖突。 編譯器通過struct
關鍵字的存在消除了兩者之間的歧義。
首先,我建議永遠不要使用結構名稱和相同的類型名稱。 使用typedef struct QUEUE_ITEM {...} queue_item_t;
至於問題:如果你想創建一個“遞歸數據結構”,即一個指向自身實例的數據結構,那么你必須能夠告訴編譯器“這個字段是指向我們自己的一個指針你完全不知道我們的樣子,因為我還在定義它,所以只需為指針保留空間“。 要做到這一點,你宣布
struct T {
...
struct T *ptr;
....
};
隨着最后} queue_item_t;
您為結構創建一個新名稱。
“struct foo {...}”是一回事。 它定義了一個結構,你需要在你使用它的每個地方輸入“struct foo”。
“typedef ... foo”定義了一個新類型,所以你只需在你使用它的地方輸入“foo”。
“typedef struct foo {...} foo”是一個成語,所以你可以使用兩者,最有可能只是“foo”來節省擊鍵和視覺污染。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.