[英]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.