Andreas Otto
Andreas Otto

Reputation: 329

How to define a struct in a struct and reuse the same name twice?

I have a simple C code example using a struct in a struct.

Problem: But now the code create an redefinition-error

struct ottoS {
  struct HermannS {
    int age;
  } name;
};

struct otherS {
  struct HermannS {
    int size;
  } name;
};

int main ()
{
  return 0;
}

I get the following error-message:

main.c:16:10: error: redefinition of ‘struct HermannS’
   struct HermannS {
          ^~~~~~~~
main.c:10:10: note: originally defined here
   struct HermannS {
          ^~~~~~~~

Question: how to define a struct in a struct and reuse the name HermannS ?

better Question: is there a gcc extension (prefix) to hide this error? → but this would be a very high price to pay for a simple doxygen documentation issue.

Upvotes: 0

Views: 1271

Answers (4)

tstanisl
tstanisl

Reputation: 14107

As the program is ill-formed it will not compile. However if struct HermannS is never used except the declaration then you could use the following trick.

If HermannS is removed then ottoS.name and otherS.name would become anonymous structs and the code would compile. All anonymous structs are independent types. Just pass -DHermannS= to the GCC's command.

gcc prog.c -DHermannS=

It will add a macro HermannS that expands to an empty token.

Do not pass this option to doxygen to let it generate a proper documentation.

Upvotes: 1

tstanisl
tstanisl

Reputation: 14107

C standard say in section 6.7.2.1 para 8

The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit.

So all structs within the same translation unit share the same namespace. HermannS is redefined thus code is ill-formed.

Some workaround would be adding a prefix with the parent structure name:

struct ottoS {
  struct ottoS_HermannS {
    int age;
  } name;
};

struct otherS {
  struct otherS_HermannS {
    int size;
  } name;
};

Latest C standards allow the implementation to accept characters from the extended set like $. It will help avoid collisions with more conventional names. It works with gcc. However, the code will no longer be portable.

struct ottoS {
  struct ottoS$HermannS {
    int age;
  } name;
};

struct otherS {
  struct otherS$HermannS {
    int size;
  } name;
};

It mimics :: operator form C++ a bit. You could use some other unicode character and use it to postprocess your Doxygen documentation with sed-like tool. I mean replacing magic character with ::.

Upvotes: 1

Marco Bonelli
Marco Bonelli

Reputation: 69306

You can't, as the compiler is telling you, and you really do not need to either. If you're not using that structure anywhere else, just don't name it:

struct ottoS {
  struct {
    int age;
  } name;
};

struct otherS {
  struct {
    int size;
  } name;
};

The only other (obvious) solution is to name the two inner structs differently.

If your logic/code/documentation is based on the fact that you need those two different structures to have the same name, then I would advise revisiting the logic, because it looks flawed.

is there a gcc extension (prefix) to hide this error?

No there is not. This is not a simple error, it's invalid C code: you are effectively defining two different types under the same name. The compiler will not be able to compile your code unless you avoid this.

Upvotes: 1

John Bode
John Bode

Reputation: 123458

A struct declaration does not create a new namespace in C the way it does in C++, so you can't create type names that are "local" to a struct type. The tag name HermannS can only be used for one struct type definition.

C has four name spaces:

  • all labels (disambiguated by : or goto);
  • all tag names (disambiguated by struct, union, or enum)
  • member names (disambiguated by . or ->)
  • all other names (typedef names, enumeration constants, variable names, function names, etc.)

Unfortunately, what you're trying to do won't work in C - you'll have to use a different tag name for each inner struct definition.

Upvotes: 3

Related Questions