tags:

views:

407

answers:

5
struct {
    char a;
    int b;
} x;

Why would one define a struct like that instead of just declaring it as:

struct x {
    char a;
    int b;
};

Thanks

+4  A: 

In the first case you are declaring a variable. In the second, a type. I think a better approach would be:

typedef struct tag_x {
    char a;
    int b;
} x;
fbinder
OK, but what about the question: Why would you define a struct one way instead of another?
Rob Kennedy
Why use `tag_x` and `x` to refer to the same thing. Structure and union and enum tags are in a separate namespace from the ordinary identifiers namespace where typedefs are defined, so there is no conflict -- and C++ effectively creates 'typedef struct x { ... } x;' automatically.
Jonathan Leffler
Might be good to edit to include the usage:x my_struct;my_struct.a = 'a';my_struct.b = 1;
ThePosey
Jonathan: Strictly speaking in C++ the compiler does not create the typedef for you, it allows you to create instances of the type without the struct keyword, but that is not the same as a typedef. There are subtle and not so subtle differences. In the code: 'typedef struct x { int a; } y; void x() {} void y() {}', declaring the x function is correct as it does not collide with the struct x. On the other hand, y cannot be redeclared as a function as it will collide with the typedef-ed definition.
David Rodríguez - dribeas
@dribeas: wow! I have little doubt you are right. I think it would be lousy coding to try what you show, but that's never stopped anybody writing such code - either deliberately or accidentally - before. For the purposes of the OP, the statement qualified with 'effectively' is probably close enough to accurate not to mislead seriously - and your note clarifies in case of doubt. Thanks for the info.
Jonathan Leffler
+2  A: 

The first is equivalent to

struct unnamed_struct {  char a;    int b;};
unnamed_struct x;

only that the struct type has no name.

peterchen
Only in C++; in C, you need 'struct unnamed_struct x;'.
Jonathan Leffler
+4  A: 

The first defines an variable named 'x' whose type is an unnamed structure.

The second defines a structure named x, but doesn't define anything that uses it.

jesup
+18  A: 

In the first case, only variable x can be of that type -- strictly, if you defined another structure y with the same body, it would be a different type. So you use it when you won't ever need any other variables of the same type. Note that you cannot cast things to that type, declare or define functions with prototypes that use that type, or even dynamically allocate variables of that type - there is no name for the type to use.

In the second case, you do not define a variable - you just define a type struct x, which can then be used to create as many variables as you need of that type. This is the more normal case, of course. It is often combined with, or associated with, a typedef:

typedef struct x
{
    char a;
    int b;
} x;

Usually, you'd use a more informative tag name and type name. It is perfectly legal and safe to use the same name for the structure tag (the first 'x') and the typedef name (the second 'x').

To a first approximation, C++ automatically 'creates a typedef' for you when you use the plain 'struct x { ... };' notation (whether or not you define variables at the same time). For fairly complete details on the caveats associated with the term 'first approximation', see the extensive comments below. Thanks to all the commentators who helped clarify this to me.

Jonathan Leffler
don`t know about first case details, thanks for pointing it out
chester89
Good explanation. And also notice that for the first, you cannot place it at namespace scope.
Johannes Schaub - litb
"C++ in effect does that automatically for you when you use the plain 'struct x { ... };' notation" Unless there is a function of the same name visible, in which case C++ can only use 'struct x' as a typename, not x alone, just the same as C.
Steve Jessop
@onebyone: what you are saying is substantially the same as what @dribeas said in response to my comment to the answer by @fbinder. I'm wondering if I should drag these comments into the actual answer?
Jonathan Leffler
@litb: are you saying that you could not do: `namespace z { struct { ... } x; }` and then refer to it `using z::x;`, for example? If so, why? If that isn't what you're saying, please can you clarify?
Jonathan Leffler
yes, that's what i'm saying. But it's not special to declaring it inside user defined namespaces. You may also not declare `x` at global namespace scope. The reason for that is: `x` would have extern linkage, but its type has no linkage. For the declaration to be valid, its type has to have linkage if `x` has. If `x`, however, is a class member or a local, then it doesn't have linkage, and so its type doesn't need to have either (this restriction is in place because of mangling difficulties for implementations, iirc).
Johannes Schaub - litb
Consult http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#527 and http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#389 for further reading.
Johannes Schaub - litb
Though, i slightly misremembered: The current Standard says "A name without linkage ..." instead of "A type without linkage ..." (that type of `x` has no name, of course). But nonetheless, comeau rejects in strict mode and GCC gives a warning. And according to the defect reports, the intent indeed was to say "a *type* without linkage ..." - this is what the defect reports resolved to and is included in the c++0x draft.
Johannes Schaub - litb
@litb: thanks for the info!
Jonathan Leffler
@Jonathan: whether it's worth mentioning in the answer. Maybe, as a footnote. It's just that you can't accurately say "C++ does the typedef for you". It's one of those unlikely-to-ever-happen gotchas of the language: What does `A a = A();` do? Answers are, (a) constructs a temporary A then copy-constructs a from it, (b) constructs a in place using the allowed optimisation, (c) returns something completely different from a function, and copy-constructs from it. This is why I name classes with an initial capital letter, and functions without ;-)
Steve Jessop
This is why i vote for a "[+] Show more" feature for SO. So the real answer can be slippy with the facts, but the show-more sections can explain throughout and without compromises :)
Johannes Schaub - litb
I'd vote for a '[+] Show more' feature too - for answers like this. I'll edit the answer slightly to make it clearer that 'C++ automatically provides a typedef' is a crude but moderately effective approximation to reality - and note that the actual reality is covered in the comments.
Jonathan Leffler
There is a defect report about this kind of typedef things, which is a pretty interesting read too: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407
Johannes Schaub - litb
+2  A: 

The two do different things:

struct {
   char a;
   int b;
} x;

Declares a variable x of type struct { char a; int b; }

struct x {
   char a;
   int b;
};

Declares a type struct x. To get a variable of that type, you would later need to do this:

struct x x = {0};
x x = {0}; // C++ only

The second one is more common, because it can make declarations shorter, especially if you have to change your struct. The first is used if you're never going to need the structure again and don't want to pollute your namespace. So basically never.

Chris Lutz