簡體   English   中英

為什么在C中的struct聲明中使用typedef名稱兩次?

[英]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_tstruct _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 ,其中包含一個成員nextad 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.

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