2

I'm working on recompiling a C project and I'm not sure how do I fix this problem in a right way. Here is a situation -

a.h

#ifndef A_H
#define A_H
typedef int INT; 
// other variables and function definition
#endif

b.h

#ifndef B_H
#define B_H
typedef int INT;
// other variables and function definition
#endif

main.c

#include "a.h" 
#include "b.h"

int main()
{
    INT i = 10; 
    return 0;
}

The error I get in Linux with gcc:

In file included from ./main.c,

    ./b.h:<linenumber>: error: redefinition of typedef ‘INT’
    a.h.h:<linenumber>: note: previous declaration of ‘INT’ was here

I have to include both headers due to other variables and functions. I haven't written this code, but this seems to compile in my Solaris environment which is strange. What can I do to fix this ?

phuclv
  • 37,963
  • 15
  • 156
  • 475
SwapnilShivhare
  • 105
  • 2
  • 5
  • 2
    replace typedef by `#define` macro. same #define works. – Jean-François Fabre Apr 11 '18 at 14:16
  • 2
    The usual way is to use a sound naming convention together with a sound program design. If `INT` is something unrelated to both "a" and "b", then clearly it should not be declared in those headers. As a side note, you shouldn't invent your own garage standard of integer types. Use stdint.h. – Lundin Apr 11 '18 at 14:23
  • This is working. Thanks!! But why #define works here and not the typedef? – SwapnilShivhare Apr 11 '18 at 14:29
  • 3
    @SwapnilShivhare `#define` and `typedef` are two very different things. The first works by textual substitution, the second actually creates a new type. It works with `#define` because it's legal to redefine a macro defined earlier, provided that it is the same definiton. – Jabberwocky Apr 11 '18 at 14:36
  • 4
    Note that [C11 §6.7 Declarations ¶3](https://port70.net/~nsz/c/c11/n1570.html#6.7p3) allows: _a typedef name may be redefined to denote the same type as it currently does, provided that type is not a variably modified type;_ so you can't be using `-std=c11` or `-std=gnu11` amongst your compiling options. Or, you must either be using an older version of GCC (meaning GCC 4 or older) because GCC version 5 or later defaults to C11 mode, or you must be deliberately specifying an older version of the standard. However, you might legitimately decide not to use the feature because of compatibility. – Jonathan Leffler Apr 11 '18 at 14:45

2 Answers2

9

Probably the native compiler on Solaris accepts that you can redefine a typedef (probably provided that the new typedef is identical to the previous one which is the case here).

I'd introduce another header file mytypes.h like this:

mytypes.h

#ifndef MYTYPES_H
#define MYTYPES_H
typedef int INT;     
#endif

Include mtypes.h whereever INT is used, possibly even in main.c:

a.h

#ifndef A_H
#define A_H
#include "mytypes.h"   // can be removed if INT is not used in a.h
// other variables and function definition
#endif

b.h

#ifndef B_H
#define B_H
#include "mytypes.h"   // can be removed if INT is not used in b.h
// other variables and function definition
#endif

main.c

#include "a.h" 
#include "b.h"
#include "mytypes.h"  // not really necessary because it's already included
                      // via a.h and b.h, but still good practice

int main()
{
    INT i = 10; 
    return 0;
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
1

If you are allowed to change the library code or compiler options then Michael Walz's answer is the way to go

In the unfortunate case that it's not changeable then it can be worked around by renaming before including the header then undefine it

#define INT INT_A
#include "a.h"
#undef INT

#define INT INT_B
#include "b.h"
#undef INT

Now just use INT_A for all the interfaces in a.h instead of INT. Same to INT_B in b.h

phuclv
  • 37,963
  • 15
  • 156
  • 475