'Forward declaration issue, two compilers

I've been developing in C using eclipse as my IDE in my virtual machine with ubuntu, I've made some progress and I wanted to test them in the real product which is an embedded system using powerpc.

In order to compile that program for our product I use Code::Blocks in Windows but the compiler is a powerpc version of the gcc.

The same code is giving me an error in the powerpc version that doesn't appear in the ubuntu version.

I have two header files gral.h and module_hand.h as follows:

The gral.h file:

#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_

#include "module_hand.h"

typedef struct PROFILE
{
    module_t  mod;    // this one comes from module_hand.h
    int       var1;   // some other random variables
} profile_t;

#endif /* HEADERS_GRAL_H_ */

The module_hand.h is defined as follows

#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_

#include <stdint.h>

#include "gral.h"

typedef struct PROFILE profile_t;

typedef struct module
{
    char  name[30];       // name of module
    char  rev[30];        // module revision
    char  mfr[30];        // manufacturer
} module_t;

int Mod_Init(profile_t *profile);
/*  some other random functions */

#endif /* HEADERS_MODULE_HAND_H_*/

As you'll see, I don't use the PROFILE struct in the module struct, But I declare it forward to use it in the declaration of the Mod_Init function

This gives me a Error: redefinition of typedef 'profile_t' and error: previous declaration of 'profile_t' was here

If I remove the forward declaration the error is Error: parse error before '*' token where the line number is the line of the function declaration.

My doubt is what am I missing, and why gcc in Ubuntu does compile it with no problem.



Solution 1:[1]

Well I read your answers and comments and decided to try another approach.

As some of you said, I had some kind of recursion, I wanted to keep every structure within its respective header file, but now, I dropped the idea and merged the structures in one file only.

My new approach:

Gral.h

#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_

typedef struct module
{
    char  name[30];       // name of module
    char  rev[30];        // module revision
    char  mfr[30];        // manufacturer
} module_t;

typedef struct PROFILE {
    module_t  mod;    // this one comes from module_hand.h
    int       var1;   // some other variables
} profile_t;

#endif /* HEADERS_GRAL_H_ */:

Module.h

#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_

#include <Gral.h>

int Mod_Init(profile_t *profile);
/* some other functions */

#endif /* HEADERS_MODULE_HAND_H_*/

And when any other structure comes up, I'll declare it in Gral.h and include the header file.

Regarding the compilers, they aren't the same version. The powerpc is quite old now. That would explain the powerpc compilation errors.

Thank you again.

Solution 2:[2]

Your powerpc compiler is enforcing the C99 rule that

If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except for tags as specified in 6.7.2.3.

(C99 6.7/3)

Your Linux compiler is observing the relaxed version of that rule that was introduced in C11:

If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except that:

  • a typedef name may be redefined to denote the same type as it currently does, provided that type is not a variably modified type;
  • tags may be redeclared as specified in 6.7.2.3.

(C11 6.7/3; also C17 6.7/3)

Supposing that the compilation options are the same, the behavior difference surely arises from using different versions of GCC. More recent versions default to more recent versions of the language.

You could try adding -std=gnu11 or -std=c11 to the command-line options (for both targets) to try to get consistency. If your powerpc version of GCC is too old to accept those then you really need to update to a newer version.

Note also, however, that you don't need to have this problem in the first place. Given that module_hand.h includes gral.h, the former has no need whatever to redefine a typedef that the latter already defines.

Moreover, the fact that these two headers each include the other is a strong suggestion that they ought to be combined into one. Multiple-inclusion guards prevent an actual loop, but they are not an adequate solution.

Solution 3:[3]

In the gral.h header file, you define profile_t using typedef, then you redefine profile_t with another typedef in module_hand.h. You should just define the struct PROFILE in gral_h and include gral.h in module_hand.h.

gral.h:

#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_

#include "module_hand.h"

typedef struct PROFILE {
    module_t  mod;    // this one comes from module_hand.h
    int       var1;   // some other random variables
} profile_t;

#endif /* HEADERS_GRAL_H_ */:

module_hand.h:

#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_

#include <stdint.h>

typedef struct module
{
    char  name[30];       // name of module
    char  rev[30];        // module revision
    char  mfr[30];        // manufacturer
} module_t;

int Mod_Init(struct PROFILE *profile);
/* some other random functions */

#endif /* HEADERS_MODULE_HAND_H_*/

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ad_valle
Solution 2 John Bollinger
Solution 3