5

I am aware of two possible ways to define and use structs:

#1 
struct person
{
    char name[32];
    int age;
};

struct person dmr = {"Dennis Ritchie", 70};

#2
typedef struct
{
    char name[32];
    int age;
} person;

person dmr = {"Dennis Ritchie", 70};

The interesting property of the first way is that both the type and the variable can have the same name:

struct person person = {"Sam Persson", 50};

Is that idiomatic in C? Is it guaranteed to work in C++? Or are there corner cases I should be aware of?

Note that I am not interested in pure C++ answers (e.g. "use std::string instead of char[32]"). This is a question about C/C++ compatibility.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • I would not call that "interesting property" it is rather obscuring property. It is better to keep type names starting from upper case - for distinguishing type and variable names. – Agnius Vasiliauskas Oct 29 '11 at 09:04
  • I have marked this as duplicate of [typedef struct vs struct definitions](http://stackoverflow.com/questions/1675351/typedef-struct-vs-struct-definitions). Technically you can consider that it is not (the other question deals only with C) but the semantics are the same in C++ with the single difference that lookup will also find symbols in the user-defined identifier space if it does not find them in the global identifier space. That is also treated in the accepted answer (that contains bits of c++) – David Rodríguez - dribeas Oct 29 '11 at 12:59
  • 1
    Also, they are **not** two ways of defining a `struct`, there is a single way of defining a `struct` (which can have or not a name), and there are `typedef`s (which can be applied to a named or unnamed type), but they are not two ways of defining a `struct` at any rate. And you are missing 3), combining both: `typedef struct type {} type;` for what it's worth (which is the idiomatic C way) – David Rodríguez - dribeas Oct 29 '11 at 13:03

4 Answers4

3

struct are compatible between C & C++ only when they are POD-s.

I tend to code something like:

struct person_st { char name[32]; int age; };
typedef struct person_st Person_t;
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
2

I declare them to have the same name in both the struct tag and global identifier namespaces:

#ifdef __cplusplus
extern "C" {
#endif

typedef struct person
{
    char name[32];
    int age;
} person;

#ifdef __cplusplus
}
#endif

In use, that requires no use of the struct tag in both C and C++ translations:

person dmr = {"Dennis Ritchie", 70};

If you prefer the struct tag in some places, you could also use it that way.

The obvious benefit is that the type may be referred to by either identifier in both namespaces, regardless of language.

justin
  • 104,054
  • 14
  • 179
  • 226
1
struct person person = {"Sam Persson", 50};

It is not idiomatic to use the same identifier for a type and a variable. In Unix, it is typical to use an abbreviated version for the variable name, e.g: struct stat st, struct timeval tv, ... the same way fd is a typical name for a file descriptor variable.

ninjalj
  • 42,493
  • 9
  • 106
  • 148
0

I'm not sure if it would be completely correct in standard C++, but I tested with g++ -pedantic -Wall and got no errors or warnings (note that this doesn't necessarily mean it's completely standard. g++, even with -pedantic, doesn't go through the trouble of giving warning for all non standard code.) (Does someone know the c++ spec well enough to comment on whether it is actually standard or not?)

The thing with writing:

struct person person = {...};

is that in C++, person both refers to the variable and to the type. In C, this wasn't a problem simply because person is not the type (struct person is). Although from the context, with the few tests I wrote with g++, the compiler had no problem understanding when I am asking for the variable and when for the type, I do think it might get confused at some point. One confusing thing that I discovered is that if you have:

struct person *person = ...;

then sizeof(person) returns the size of the variable, while to get the size of the type, you should write sizeof(struct person) which I can assure you, no c++ coder would remember to write the stuct.

It is best to avoid all kinds of confusion. I usually do this for code that could be used both in C and C++:

typedef struct person
{
    ...
} person;

Giving a name to the struct that is being typedefed allows the programmer to use either person or struct person. So, a bit of flexibility (not to mention you don't have to change already written code after typedefing the struct.

Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • 1
    For the `sizeof` example. see the C++ standard §9.1 ¶2 _If a class name is declared in a scope where a variable, function, or enumerator of the same name is also declared, then when both declarations are in scope, the class can be referred to only using an elaborated-type-specifier_ – ninjalj Oct 29 '11 at 09:51
  • No, in C++ for your first example `person` would refer to the variable. – Jens Gustedt Oct 29 '11 at 12:17