What is the meaning of `struct X typedef` and` typedef struct X`?

I have the following (working) code in an existing code base used in an include file that is used in conjunction with C and C ++, compilation on MSVC (2010) and 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, the correct definition should look like this:

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

Is there any purpose to have the form below? Did I miss something?

+54
c ++ c struct visual-studio-2010
Jun 15 '14 at 8:22
source share
5 answers

The fact that both typedef <type> <alias> and <type> typedef <alias> valid simply comes from the definition of the grammar of the language.

typedef classified as a storage class specifier (just like static , auto ), and the type itself is known as a type specifier. From the syntax definitions in section 6.7 of the standard, you will see that they can be used interchangeably:

 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 that this is true for both structures and nonstructures, which means double typedef trouble; also valid.)

+56
Jun 15 '14 at 9:03
source share

As others have said, typedef is a storage class specifier, and, as with other storage class specifiers, you can also put a specifier between the type and the declarator.

While this is true, and it is also a form that should be avoided since C designates it as an obsolete function:

(C11, 6.11.5p1) "The placement of a storage class specifier other than the start of the declaration qualifiers in the declaration is an obsolete function.

+18
Jun 15 '14 at 9:34
source share

Both have the same meaning. Both of these forms are valid:

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

You can typedef structure above anyway:

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

or

 typedef struct { USHORT x; } X, *PX; // typedef <existing_type> <new_type> 
+6
Jun 15 '14 at 8:23
source share

You are indeed allowed to specify all declaration qualifiers in any order! The positions of any pointers * and the actual declarator (the name of a variable or a new type) matter, but all that typedef int unsigned const static , etc., can be in any order.

If you look at the official C grammar, it just says:

 declaration: declaration-specifiers init-declarator-list ; 

declaration-specifiers - all storage class declaration-specifiers ( typedef , extern , etc.), type specifiers (actual type, for example int or struct X ), type classifiers ( const and volatile ) and several other less common ones. Their order is not important. The second part is init-declarator-list , which is the name of a variable or a new type (in the case of typedef), any characters * , variable initialization ( int x = 3 ), and much more. The order of things regarding the declarator is important, but not the order in the qualifiers of declarations.

+5
Jun 15 '14 at 9:09
source share

Disclaimer: This is not a technical, but a practical answer. See Other Technical Answers. This answer is stubborn and subjective, but please bear with me while I try to explain the big picture.

struct is a strange beast because the material you put between the closing bracket } and the semicolon ; , refers to content inside or in front of these brackets. I know why this is so, and grammatically it makes sense, but personally I find it very controversial, since curly braces usually mean an area:

Counterintuitive 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 and typedef , if used like that. As shown below, it is very easy to declare a variable instead of a type randomly. The compiler has limited help because almost all combinations are grammatically correct. They just don't necessarily mean what you're trying to express. This is a pit of despair .

Invalid 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 brace. The cost of additional lines of code is easily outweighed by the intuitive syntax. I argue that this approach makes it easy to do the right thing and annoy doing the wrong thing .

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; vx = 0; vy = 1; 
+5
Jun 15 '14 at 23:01
source share



All Articles