Search code examples
cstructunions

A reused named struct as a nested struct triggers a redefinition error in GCC


This is a contrived example, but expresses the core problem. I have a union and a structure with the same nested structure from an existing code base:

typedef union _MyUnion
{
  unsigned int A;
  struct _MyNestedStruct
  {
    int field
  } MyNestedStruct;
} MyUnion;

and

typedef struct _MyStruct
{
  struct _MyNestedStruct
  {
    int field
  } MyNestedStruct;
} MyStruct;

If I compile this under the Green Hills Compiler (GHC), then there are no problems. Compiling under GCC gives the error "error: redefinition of 'struct _MyStruct'".

First of all, why was I able to successfully compile with a named structure as a nested structure? I suspect that GHC is compiling with some C++ rules, or it supports named structures in a nested structure.

Second, what would allow me to successfully compile without any significant code changes? I know I can just delete the _MyNestedStruct from the nested structure, but does this have any consequences?


Solution

  • In C there are no namespace scopes, implicit or explict, so all the structure names share the same name space. Hence, struct _MyNestedStruct is defined twice and it is an error. GCC is correct, GHC is not.

    If it were C++, then the code would be correct, because each struct would create a different namespace scope and so there is no name clash.

    Solutions that I can think of:

    A) If the structures are actually the same, define it just once outside of the other ones (you could have it inside the first one, but that would be weird).

    struct _MyNestedStruct
    {
        int field
    };
    
    typedef union _MyUnion
    {
      unsigned int A;
      struct _MyNestedStruct MyNestedStruct;
    } MyUnion;
    
    typedef struct _MyStruct
    {
      struct _MyNestedStruct MyNestedStruct;
    } MyStruct;
    

    B) Name the two structures differntly. In C the name is not so important, as long the definition is identical.

    C) Use nameless structures. I reckon you will not be using these names at all:

    typedef union _MyUnion
    {
      unsigned int A;
      struct
      {
        int field;
      } MyNestedStruct;
    } MyUnion;
    
    typedef struct _MyStruct
    {
      struct
      {
        int field;
      } MyNestedStruct;
    } MyStruct;
    

    BTW, remember that any name beginning with and underscore plus an uppercase is reserved for the implementation and should not be defined by the user.