簡體   English   中英

C中這兩種typedef樣式有什么區別?

[英]What are the differences between these two typedef styles in C?

我很好奇當typedefing一個枚舉或結構時,這里的區別是什么。 這兩個塊之間在語義上有什么區別嗎?

這個:

typedef enum { first, second, third } SomeEnum;

還有這個:

enum SomeEnum { first, second, third };
typedef enum SomeEnum SomeEnum;

結構相同的交易。 我已經看到兩者都在使用,他們似乎都在C或Objective-C中做同樣的事情。 是否存在真正的差異,或者只是偏好您可以使用哪種風格?

不同之處在於第二種方法聲明了一個名為enum SomeEnum的類型,並且還聲明了一個typedef-name SomeEnum - 該類型的別名。 它實際上可以組合成等效的單行程

typedef enum SomeEnum { first, second, third } SomeEnum;

這很明顯,兩種方法之間的唯一區別是enum關鍵字后面是否有名稱。 使用第二種方法,您可以使用SomeEnum eenum SomeEnum e (無論您喜歡哪種方式)聲明該枚舉類型的對象。

第一種方法僅為最初的匿名枚舉類型聲明typedef-name SomeEnum ,這意味着您僅限於SomeEnum e聲明。

因此,只要您在聲明中僅使用typedef-name SomeEnum ,兩者之間就沒有區別。 但是,在某些情況下,您可能必須使用類型enum SomeEnum的完整原始名稱。 在第一種方法中,該名稱不可用,因此您將失去運氣。

例如,如果在上述聲明之后,您還在某個嵌套范圍中聲明了名為SomeEnum的變量

int SomeEnum;

變量的名稱將隱藏枚舉的typedef-name,從而使此聲明非法

SomeEnum e; /* ERROR: `SomeEnum` is not a type */

但是,如果在聲明枚舉時使用第二種方法,則可以使用完整類型名稱解決此問題

enum SomeEnum e; /* OK */

如果在聲明枚舉類型時使用第一種方法,則無法實現這一點。

當與結構一起使用時,當你需要一個自引用類型(一個包含指向同一類型的指針的類型)時, struct之后的名稱是必須的,比如

typedef struct SomeStruct {
  struct SomeStruct *next;
} SomeStruct;

最后,在第二種方法中,typedef名稱是完全可選的。 你可以簡單地宣布

enum SomeEnum { first, second, third };

每次需要引用此類型時,只需使用enum SomeEnum

是的,存在語義差異。 第二個片段聲明了標記標識符,但第一個標識符沒有。 兩者都聲明一個普通的標識符。

這意味着,對於第一個,此代碼無效,但對於第二個,它是:

enum SomeEnum foo;

據我所知,代碼中它們之間沒有其他語義差異。 對於結構和聯合,遞歸類型需要第二種形式,可能與一個聲明中的typedef結合使用

typedef struct node {
  struct node *parent; // refer to the tag identifier
} node;

普通標識符在struct的說明符中尚不可見,因此您需要通過已聲明的標記標識符來引用該結構。 標簽標識符通過在“struct”,“union”或“enum”之前加上它們來引用,而普通標識符在沒有前綴的情況下引用(因此名稱為“普通”)。

除了將引用結構,聯合和枚舉的標識符與引用值的標識符分開時,標記標識符對於創建前向聲明也很有用:

/* forward declaration */
struct foo; 

/* for pointers, forward declarations are entirely sufficient */
struct foo *pfoo = ...;

/* ... and then later define its contents */
struct foo {
  /* ... */
};

Typedef名稱不能在同一范圍內重復聲明(與C ++相反),並且它們需要引用現有類型,因此它們不能用於創建前向聲明。

唯一真正的區別是,在第二種情況下,您可以使用以下內容:

enum SomeEnum x;

而第一個支持:

SomeEnum x;

人誰已經用C寫很長的時間,定義一個struct沒有struct往往關鍵詞“感覺”奇怪...

第一個表單創建一個匿名enum類型並SomeEnum創建一個SomeEnum別名。

第二種形式創建enum SomeEnum類型和SomeEnum別名。

(在C中,類型有單獨的命名空間。也就是說, struct Fooenum Foo不同,它與Foo不同。)

對於struct這比enum更重要,因為如果你的struct是自引用的,你需要使用第二種形式。 例如:

struct LinkedListNode
{
    void* item;
    struct LinkedListNode* next;
};

typedef struct LinkedListNode LinkedListNode;

第一種形式無法實現上述目標。

對於struct真正的區別不僅僅在於命名。

這是有效的C:

struct SomeEnum { struct SomeEnum *first; };

這不是:

typedef struct { SomeEnum *first; } SomeEnum;

having a definition for the struct. 添加到user207442的評論,有可能為源代碼模塊,而為結構的定義聲明式“結構FOO *”的變量。 這樣的模塊將無法取消引用這樣的指針,但可以將它們傳遞給其他模塊或從其他模塊傳遞。

例如,可以使用“typedef struct _USERCONSOLE * USERCONSOLE;”來為頭文件定義類型“USERCONSOLE”。 代碼表示#include的頭文件可以包含USERCONSOLE類型的變量,並將這些變量傳遞給/來自知道_USERCONSOLE實際是什么的模塊,而頭文件不必暴露結構的實際定義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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