struct X typedef和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被分类为存储类specfifier (就像staticauto ),types本身被称为types说明符 。 从标准的第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是一个存储类说明符,与其他存储类说明符一样,您也可以将说明符放在types和声明程序之间。

虽然这是有效的,但它也是一种应该避免的forms,因为C标记为过时的特征:

(C11,6.11.5p1)“在声明中声明说明符开头以外的存储类说明符的放置是过时的function。

两者具有相同的含义。 这两种forms都是有效的:

 typedef <existing_type> <new_type> <existing_type> typedef <new_type> 

您可以用任何方式typedef上面的结构体:

 struct X { USHORT x; }typedef X, *PX; // <existing_type> typedef <new_type> 

要么

 typedef struct { USHORT x; } X, *PX; // typedef <existing_type> <new_type> 

你真的可以把所有的声明说明符以任何你想要的顺序! 任何*指针的位置和实际的声明符(variables或新的types名称)的问题,但所有的typedef int unsigned const static等东西可以以任何顺序。

如果你看看C的官方语法,它只是说:

 declaration: declaration-specifiers init-declarator-list ; 

declaration-specifiers是所有存储类说明符( typedefextern等),types说明符(实际types,如intstruct X ),types限定符( constvolatile )以及其他一些不太常见的types。 他们的顺序并不重要。 第二部分是init-declarator-list ,它是variables或新types的名称(在typedef的情况下),任何*字符,variables的初始化( 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 s和typedef的密集语法,那么可能会出现很多微妙的东西。 如下所示,非常容易声明一个variables而不是偶然的types。 编译器只有有限的帮助,因为几乎所有的组合在语法上都是正确的。 他们只是不一定意味着你想expression的东西。 这是一个绝望的坑 。

错误的例子:

 // 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; vx = 0; vy = 1;