简体   繁体   English

struct X typedef与def type struct X是什么意思?

[英]What is the meaning of `struct X typedef` vs. `typedef struct X`?

I have the following (working) code in an existing code base, used in include file that is shared between C and C++, compiling on MSVC (2010) and Windows DDK: 我在现有代码库中有以下(有效)代码,用于C和C ++之间共享的包含文件中,并在MSVC(2010)和Windows DDK上进行编译:

struct X {
    USHORT x;
} typedef X, *PX;

And: 和:

enum MY_ENUM {
    enum_item_1,
    enum_item_2 
} typedef MY_ENUM;

As far as I know, correct definition should look like this: 据我所知,正确的定义应如下所示:

typedef struct {
    USHORT x;
} X, *PX;

Is there any purpose for having the form below? 填写以下表格有什么目的? Am I missing something? 我想念什么吗?

The fact that both typedef <type> <alias> and <type> typedef <alias> are valid simply comes from the language grammar definition. typedef <type> <alias><type> typedef <alias>均有效的事实仅来自语言语法定义。

typedef is classified as a storage-class specfifier (just like static , auto ), and the type itself is known as the type-specifier . typedef被分类为存储类说明符 (就像staticauto ),类型本身称为type-specifier From the syntax definitions in section 6.7 of the standard, you'll see that these are free to be interchanged: 从该标准的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

(Note, of course, that this is equally true for structs and for non-structs, meaning that double typedef trouble; is also valid.) (当然,请注意,这对于结构和非结构都同样适用,这意味着double typedef trouble;也是有效的。)

As others said, typedef is a storage-class specifier and as with other storage-class specifiers you are also allowed to put the specifier between the type and the declarator. 就像其他人所说的那样, typedef是一个存储类说明符,与其他存储类说明符一样,您也可以将说明符放在类型和声明符之间。

While this is valid and it is also a form that should be avoided as C marked it as an obsolescent feature: 尽管这是有效的,并且也是应避免的一种形式,因为C将其标记为过时的功能:

(C11, 6.11.5p1) "The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature." (C11,6.11.5p1)“在声明中将存储类说明符放在声明说明符的开头以外的地方是过时的功能。”

Both have the same meaning. 两者具有相同的含义。 Both of these two forms are valid: 这两种形式均有效:

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

You can typedef the above struct in either ways: 您可以通过两种方式typedef上述结构的def:

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

or 要么

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

You really are allowed to put all the declaration specifiers in any order you want! 确实允许您按所需的任何顺序放置所有声明说明符! The positions of any * pointers and the actual declarator (the variable or new type name) matter, but all that typedef int unsigned const static etc. stuff can be in any order. 任何*指针和实际声明符(变量或新类型名称)的位置都很重要,但是所有typedef int unsigned const static等东西都可以以任何顺序排列。

If you look at the official grammar of C, it just says: 如果您看一下C的官方语法,它只会说:

declaration:
    declaration-specifiers init-declarator-list ;

The declaration-specifiers are all the storage class specifiers ( typedef , extern , etc.), type specifiers (the actual type, like int or struct X ), type qualifiers ( const and volatile ), and a few other less common ones. declaration-specifiers是所有存储类说明符( typedefextern等),类型说明符(实际类型,如intstruct X ),类型限定符( constvolatile )以及其他一些较不常用的说明符。 Their order is not important. 他们的顺序并不重要。 The second part is the init-declarator-list , and it's the variable or new type name (in the case of a typedef), any * characters, the initialization of the variable ( int x = 3 ), and more. 第二部分是init-declarator-list ,它是变量或新类型名称(在typedef的情况下),任何*字符,变量的初始化( int x = 3 )等。 The order of things in the declarator part is important, but not the order in the declaration specifiers. 声明器部分中的事物顺序很重要,但声明说明符中的事物顺序并不重要。

Disclaimer: This is not a technical but a practical answer. 免责声明:这不是技术性的而是实际的答案。 Refer to the other answers for technical matters. 有关技术问题,请参阅其他答案。 This answer reads opinionated and subjective but please bear with me while I try to explain the bigger picture. 这个答案读起来很主观,但是在我尝试解释大局的时候请多多包涵。

struct is a strange beast because the stuff you put between the closing bracket } and the semicolon ; struct是一个奇怪的野兽,因为你的右括号之间把东西}和分号; refers to the content inside or before those brackets. 是指这些括号内或之前的内容。 I know why that is, and grammatically it does make sense, but personally I find it very counter-intuitive as curly brackets usually mean scope: 我知道为什么会这样,而且从语法上来说确实是有道理的,但是我个人认为它非常违反直觉,因为大括号通常表示范围:

Counter-intuitive examples: 违反直觉的例子:

// 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;

There are so many subtle things that can go wrong with the dense syntax of struct s and typedef s if used like this. 如果像这样使用structtypedef的密集语法,那么有很多微妙的地方可能会出错。 As shown below it is very easy to declare a variable instead of a type by accident. 如下所示,很容易意外地声明变量而不是类型。 The compiler is only of limited help because almost all combinations are grammatically correct. 编译器的帮助有限,因为几乎所有组合在语法上都是正确的。 They just don't necessarily mean what you try to express. 它们只是不一定意味着您要表达的内容。 It is a pit of despair . 这是一个绝望

Wrong examples: 错误的例子:

// 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;
};

For reasons of readability and maintenance I prefer to declare everything separately and never put anything behind the closing curly bracket. 出于可读性和维护性的考虑,我宁愿单独声明所有内容,并且切勿将任何内容放在大括号后面。 The cost of additional lines of code are easily outweighed by intuitive syntax. 直观的语法可以轻松地抵消额外代码行的成本。 I argue that this approach makes it easy to do the right things and annoying to do the wrong things . 我认为这种方法使做正确的事情变得容易,而使做错的事情变得烦人

Intuitive examples: 直观的例子:

// 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM