What's the syntactically proper way to declare a C struct?
Well, the obvious difference is demonstrated in your main
:
struct foo a;
bar b;
baz c;
The first declaration is of an un-typedef
ed struct
and needs the struct
keyword to use. The second is of a typedef
ed anonymous struct
, and so we use the typedef
name. The third combines both the first and the second: your example uses baz
(which is conveniently short) but could just as easily use struct _baz
to the same effect.
Update: larsmans' answer mentions a more common case where you have to use at least struct x { }
to make a linked list. The second case wouldn't be possible here (unless you abandon sanity and use a void *
instead) because the struct
is anonymous, and the typedef
doesn't happen until the struct
is defined, giving you no way to make a (type-safe) pointer to the struct
type itself. The first version works fine for this use, but the third is generally preferred in my experience. Give him some rep for that.
A more subtle difference is in namespace placement. In C, struct
tags are placed in a separate namespace from other names, but typedef
names aren't. So the following is legal:
struct test {
// contents
};
struct test *test() {
// contents
}
But the following is not, because it would be ambiguous what the name test
is:
typedef struct {
// contents
} test;
test *test() {
// contents
}
typedef
makes the name shorter (always a plus), but it puts it in the same namespace as your variables and functions. Usually this isn't an issue, but it is a subtle difference beyond the simple shortening.
It's largely a matter of personal preference. I like to give new types a name starting with a capital letter and omit the struct
, so I usually write typedef struct { ... } Foo
. That means I cannot then write struct Foo
.
The exception is when a struct
contains a pointer to its own type, e.g.
typedef struct Node {
// ...
struct Node *next;
} Node;
In this case you need to also declare the struct Node
type, since the typedef
is not in scope within the struct
definition. Note that both names may be the same (I'm not sure where the underscore convention originated, but I guess older C compilers couldn't handle typedef struct X X;
).
All your uses are syntactically correct. I prefer the following usage
/* forward declare all structs and typedefs */
typedef struct foo foo;
.
.
/* declare the struct itself */
struct foo {
short a;
int b;
foo* next;
};
Observe that this easily allows to use the typedef
already inside the declaration of the struct
itself, and that even for struct
that reference each other mutually.