[英]What is the meaning of `struct X typedef` vs. `typedef struct X`?
我在現有代碼庫中有以下(有效)代碼,用於C和C ++之間共享的包含文件中,並在MSVC(2010)和Windows DDK上進行編譯:
struct X {
USHORT x;
} typedef X, *PX;
和:
enum MY_ENUM {
enum_item_1,
enum_item_2
} typedef MY_ENUM;
據我所知,正確的定義應如下所示:
typedef struct {
USHORT x;
} X, *PX;
填寫以下表格有什么目的? 我想念什么嗎?
typedef <type> <alias>
和<type> typedef <alias>
均有效的事實僅來自語言語法定義。
typedef
被分類為存儲類說明符 (就像static
, auto
),類型本身稱為type-specifier 。 從該標准的6.7節中的語法定義中,您將看到它們可以自由互換:
declaration:
declaration-specifiers init-declarator-list ;
declaration-specifiers:
storage-class-specifier declaration-specifiers
type-specifier declaration-specifiers
type-qualifier declaration-specifiers
function-specifier declaration-specifiers
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
(當然,請注意,這對於結構和非結構都同樣適用,這意味着double typedef trouble;
也是有效的。)
就像其他人所說的那樣, typedef
是一個存儲類說明符,與其他存儲類說明符一樣,您也可以將說明符放在類型和聲明符之間。
盡管這是有效的,並且也是應避免的一種形式,因為C將其標記為過時的功能:
(C11,6.11.5p1)“在聲明中將存儲類說明符放在聲明說明符的開頭以外的地方是過時的功能。”
兩者具有相同的含義。 這兩種形式均有效:
typedef <existing_type> <new_type>
<existing_type> typedef <new_type>
您可以通過兩種方式typedef
上述結構的def:
struct X {
USHORT x;
}typedef X, *PX; // <existing_type> typedef <new_type>
要么
typedef struct {
USHORT x;
} X, *PX; // typedef <existing_type> <new_type>
確實允許您按所需的任何順序放置所有聲明說明符! 任何*
指針和實際聲明符(變量或新類型名稱)的位置都很重要,但是所有typedef
int
unsigned
const
static
等東西都可以以任何順序排列。
如果您看一下C的官方語法,它只會說:
declaration:
declaration-specifiers init-declarator-list ;
declaration-specifiers
是所有存儲類說明符( typedef
, extern
等),類型說明符(實際類型,如int
或struct X
),類型限定符( const
和volatile
)以及其他一些較不常用的說明符。 他們的順序並不重要。 第二部分是init-declarator-list
,它是變量或新類型名稱(在typedef的情況下),任何*
字符,變量的初始化( int x = 3
)等。 聲明器部分中的事物順序很重要,但聲明說明符中的事物順序並不重要。
免責聲明:這不是技術性的而是實際的答案。 有關技術問題,請參閱其他答案。 這個答案讀起來很主觀,但是在我嘗試解釋大局的時候請多多包涵。
struct
是一個奇怪的野獸,因為你的右括號之間把東西}
和分號;
是指這些括號內或之前的內容。 我知道為什么會這樣,而且從語法上來說確實是有道理的,但是我個人認為它非常違反直覺,因為大括號通常表示范圍:
違反直覺的例子:
// declares a variable named `foo` of unnamed struct type.
struct {
int x, y;
} foo;
foo.x = 1;
// declares a type named `Foo` of unnamed struct type
struct {
int x, y;
} typedef Foo;
Foo foo2;
foo2.x = 2;
// declares a type named `Baz` of the struct named `Bar`
struct Bar {
int x, y;
} typedef Baz;
// note the 'struct' keyword to actually use the type 'Bar'
struct Bar bar;
bar.x = 3;
Baz baz;
baz.x = 4;
如果像這樣使用struct
和typedef
的密集語法,那么有很多微妙的地方可能會出錯。 如下所示,很容易意外地聲明變量而不是類型。 編譯器的幫助有限,因為幾乎所有組合在語法上都是正確的。 它們只是不一定意味着您要表達的內容。 這是一個絕望的坑 。
錯誤的例子:
// mixed up variable and type declaration
struct foo {
int x, y;
} Foo;
// declares a type 'foo' instead of a variable
typedef struct Foo {
int x, y;
} foo;
// useless typedef but compiles fine
typedef struct Foo {
int x, y;
};
// compiler error
typedef Foo struct {
int x, y;
};
出於可讀性和維護性的考慮,我寧願單獨聲明所有內容,並且切勿將任何內容放在大括號后面。 直觀的語法可以輕松地抵消額外代碼行的成本。 我認為這種方法使做正確的事情變得容易,而使做錯的事情變得煩人 。
直觀的例子:
// declares a struct named 'TVector2'
struct TVector2 {
float x, y;
};
// declares a type named 'Vector2' to get rid of the 'struct' keyword
// note that I really never use 'TVector2' afterwards
typedef struct TVector2 Vector2;
Vector2 v, w;
v.x = 0;
v.y = 1;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.