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