No, this is not declaring anything, this is defining a type,
and also creating an alias for it.
In C. In C++, the issue is a bit more complex.
This is also perfectly valid C++. It defines a structure type
with no name, and defines SetupRecord as an alias for that
type.
Actually, it defines a class type with the name SetupRecord, and
also defines SetupRecord as an alias for that type. (But this
is more a compatibility hack than anything else.)
There is a fundamental difference between C and C++ here. In C,
structure names are NOT type names; in C++, they are. And C
types by structure (although if you give the struct a name, it is
part of the structure, and thus the type), C++ by name. For
example:
typedef struct { int i ; } A ;
typedef struct { int i ; } B ;
In C, you have one type ("struct {int i;}"), with two names (or
aliases to the type). In C++, you have two different types, A
and B (and A and B are also aliases for the types).
This is actually not a particularly good idea in either
language.
Opinions vary in C. I tended not to use it when I was working
in C, but a lot of programmers do.
Again, your sample below does not declare a struct, it defines a
struct type.
You mean a class type, I suppose. In C++, there aren't any
struct types.
This is perfectly valid C does as well. In both languages, it defines
a structure type named SetupRecord.
Not really. In C, it defines a structure type with the tag
SetupRecord. In C++, it defines a class type with the type name
SetupRecord.
In either language, the type can be referred to by the
two-word phrase "struct SetupRecord".
The practical effects are the same, but the actual definition of
the phrase is very different in the two languages.
In C++ only, it can also be referred to merely as SetupRecord.
That's because in C++, SetupRecord is a type name; in C, it's
not.
Fundamentally, the two languages are very different in this
regard. Practically, C++ has a couple of special case hacks so
that most C uses end up still being legal, and having (almost)
the same effect.