Search code examples
c++cgnu99

C struct with same type name as variable name?


I am working on a project where there is a .h file that contains the following lines:

File1.h

typedef struct {
int a; 
} MyData;

typedef struct {
  MyData MyData;
} MyDataContainer; 

This is compiled using gnu99 standard without any issues. However, if i include File1.h in a C++ file compiled using gcc standard gnu++17, i get errors related to the type name MyData and the instance MyData having the same name. I am not really used to working in C. Is there a reason to have the same type name as the instance name? I cannot change the C file, are there workarounds to #include File1.h in a C++ file?

Thank you in advance for your help.

File1.h compiles with no errors. When i link the library compiled using gnu99 in a library compiled in C++, it throws errors.


Solution

  • Preamble: In C++, the code in the question is ill-formed, no diagnostic required; see Variable with same name as type - which compiler is right? for Standard references.


    If you cannot modify the C file then there are no seamless, well-defined workarounds .

    It may be possible to disable the error message, in which case the behaviour of the program will be formally undefined, but is likely to work correctly:

    • in g++ 13, use -Wno-changes-meaning.
    • use -fms-extensions, but that has other effects.

    Failing that, you will have to make an intermediate layer between the C code and the C++ code, with a new function to wrap every C function the C++ code needed to call with a MyData argument; for example:

    // MyKludge.h
    typedef struct {
      Type1 myVar1;
      Type2 myVar2;
    } MyData;
    
    typedef struct {
        MyData foo;
        TypeA myVarA; 
        TypeB myVarB; 
    } MyDataContainer2; 
    
    void File1Func(MyDataContainer2 *x);
    
    // MyKludge.c
    #include "File1.h"
    #include "MyKludge.h"
    
    void File1FuncWrapper (MyDataContainer2 *x)
    {
        // Technically undefined behaviour but will probably work
        File1Func( (MyDataContainer *)x );
    
        // Definitely well-defined but could be inefficient depending on compiler
        MyDataContainer y;
        y.MyData = x->foo;
        y.MyVarA = x->MyVarA;
        y.MyVarB = x->MyVarB;
        File1Func( &y );
        x->foo = y.MyData;   // If func might change object
        x->MyVarA = y.MyVarA;
        x->MyVarB = y.MyVarB;
    }