I encountered some code reading
typedef enum eEnum { c1, c2 } tagEnum; typedef struct { int i; double d; } tagMyStruct;
I heard rumours that these constructs date from C. In C++ you can easily write
enum eEnum { c1, c2 }; struct MyStruct { int i; double d; };
Is that true? When do you need the first variant?
First, both declarations are legal in both C and C++. However, in C, they have slightly different semantics. (In particular, the way you refer to the struct later varies).
The key concept to understand is that in C, structs exist in a separate namespace. All built-in types, as well as typedefs exist in the ‘default’ namespace. That is, when I type
int, the compiler only checks this ‘default’ namespace. If I type ‘tagMyStruct’ as in your example, the compiler also only checks this one namespace. But depending which type of declaration you use, the struct may not exist in that namespace.Structs are different, and exist in a separate namespace. So if I make the following declaration:
I can not simply refer to it as mystruct. Instead, I have to specify that I want the mystruct which exists in the struct namespace:
Which gets a bit verbose and awkward in the long run. Instead, you can typedef it into the default namespace:
and now, my function can be declared in the straightforward way:
So your first example simply merges these two steps together: Declare a struct, and put an alias into the regular namespace. And of course, since we’re typedeffing it anyway, we don’t need the ‘original’ name, so we can make the struct anonymous. So after your declaration
we have a struct with no name, which has been typedef’ed to ‘tagMyStruct’ in the default namespace.
That’s how C treats it. Both types of declarations are valid, but one does not create the alias in the ‘default’ namespace, so you have to use the struct keyword every time you refer to the type.
In C++, the separate struct namespace doesn’t exist, so they mean the same thing. (but the shorter version is preferred).
Edit Just to be clear, no, C does not have namespaces. Not in the usual sense. C simply places identifiers into one of two predefined namespaces. The names of structs (and enums, as I recall) are placed in one, and all other identifiers in another. Technically, these are namespaces because they are separate ‘containers’ in which names are placed to avoid conflicts, but they are certainly not namespaces in the C++/C# sense.