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 (就像static
, auto
),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
是所有存储类说明符( typedef
, extern
等),types说明符(实际types,如int
或struct X
),types限定符( const
和volatile
)以及其他一些不太常见的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;