Search code examples
cstructtypedefforward-declarationcircular-dependency

typedef struct, circular dependency, forward definitions


The problem I have is a circular dependency issue in C header files ...Having looked around I suspect the solution will have something to do with Forward Definitions, but although there are many similar problems listed, none seem to offer the information I require to resolve this one...

I have the following 5 source files:

// fwd1.h
#ifndef __FWD1_H
#define __FWD1_H

#include "fwd2.h"

typedef
  struct Fwd1 {
    Fwd2  *f;
 }
Fwd1;

void  fwd1 (Fwd1 *f1,  Fwd2 *f2) ;

#endif // __FWD1_H

.

// fwd1.c
#include "fwd1.h"
#include "fwd2.h"
void  fwd1 (Fwd1 *f1,  Fwd2 *f2)  { return; }

.

// fwd2.h
#ifndef __FWD2_H
#define __FWD2_H

#include "fwd1.h"

typedef
  struct Fwd2 {
    Fwd1  *f;
  }
Fwd2;

void  fwd2 (Fwd1 *f1,  Fwd2 *f2) ;

#endif // __FWD2_H

.

// fwd2.c
#include "fwd1.h"
#include "fwd2.h"
void  fwd2 (Fwd1 *f1,  Fwd2 *f2)  { return; }

.

// fwdMain.c
#include "fwd1.h"
#include "fwd2.h"
int  main (int argc, char** argv, char** env)
{
  Fwd1  *f1 = (Fwd1*)0;
  Fwd2  *f2 = (Fwd2*)0;

  fwd1(f1, f2);
  fwd2(f1, f2);

  return 0;
}

Which I am compiling with the command: gcc fwdMain.c fwd1.c fwd2.c -o fwd -Wall

I have tried several ideas to resolve the compile errors, but have only managed to replace the errors with other errors ...How do I resolve the circular dependency issue with the least changes to my code? ...Ideally, as a matter of coding style, I would like to avoid putting the word "struct" all over my code.


Solution

  • The problem here is that when you do circular types, then on the first compiler run, gcc won't have the full type definitions (that's why you get the error of undefined structures and stuff), so on the appropriate places it is necessary to place the word 'struct' before the proper names. So your declarations should look something like this:

    fwd1.h:

    //fwd1.h
    #ifndef __FWD1_H
    #define __FWD1_H
    
    #include "fwd2.h"
    
    typedef struct Fwd1{
        struct Fwd2  *f;
    }Fwd1;
    
    
    void  fwd1 (Fwd1 *f1,  struct Fwd2 *f2) ;
    
    #endif // __FWD1_H
    

    fwd2.h:

    // fwd2.h
    #ifndef __FWD2_H
    #define __FWD2_H
    
    #include "fwd1.h"
    
    typedef struct Fwd2{
      struct Fwd1  *f;
    }Fwd2;
    
    void  fwd2 (struct Fwd1 *f1,  Fwd2 *f2) ;
    
    #endif // __FWD2_H
    

    Perform the equivalent changes on the function definitions on the .c. It should work like a charm.

    P.S: The purpose of a .h file is to declare all the headers, i.e: function definitions, includes, etc. that your .c will need. So no need to repeat any includes on the .c apart from the one of the respective .h.

    That means your fwd1.c should only include fwd1.h, and then all the other includes should be placed on fwd1.h.