Include Guards in C

308 views Asked by At

I have 2 header files that have to include one other.

config.h:

#ifndef CONFIG
#define CONFIG

#include "debug.h"

typedef struct Config_t {
    /* some stuff */
} Config;
#endif

debug.h

#ifndef DEBUG
#define DEBUG

#include "config.h"

void somePrintingFunction(Config* conf);
#endif

Here is the error I get:

debug.h: error: unknown type name 'Config'

config.c: warning: implicit declaration of function 'somePrintingFunction'

debug.h: error: unknown type name 'Config'

I guess it's looping in the header declaration?


Edit:

Fixed in merging both files so simplify project design. If you want a real fix check in comments.

3

There are 3 answers

4
Petr Skocik On BEST ANSWER

When config.h includes debug.h, debug.h will try to include config.h but since the CONFIG guard macro will already have been defined, the retroactive "include" of config.h will get skipped and the parsing will continue on the next line:

void somePrintingFunction(Config* conf);

without the Config type having been defined.

As StoryTeller has pointed out, you can break the mutual dependency by forward declaring the Config_t struct:

struct Config_t;
void somePrintingFunction(struct Config_t* conf);

Since C11, you can also do the typedef since C11 can handle duplicated typedefs as long as they refer to the same type.

typedef struct Config_t Config;
void somePrintingFunction(Config* conf);

(Forward declarations of aggregates (structs or unions) don't allow you to declare objects of those types (unless a full definition has already been provided) but since C guarantees that all pointers to structs or unions must look the same, they are enough to allow you to start using pointers to those types.)

6
StoryTeller - Unslander Monica On

debug.h doesn't need the other header. You can define that function just fine with a forward declaration of Config_t alone

struct Config_t;
void somePrintingFunction(struct Config_t* conf);
2
Yastanub On

The problem with this is the circular inclusion. You are actually including your function before you declare your structure. Lets say you include config.h(assuming you removed the wrong include a.h the preprocessor does this:

#include "debug.h"

typedef struct Config_t {
    /* some stuff */
} Config;

and defines the symbol CONFIG so that this file will not be included twice. Then it evaluates the remaining include:

#include "config.h"

void somePrintingFunction(Config* conf);


typedef struct Config_t {
    /* some stuff */
} Config;

and defines the symbol DEBUG. Since symbol CONFIG is defined it will not include config.ha second time and thus it is finished. Now notice how the declaration of the function is before the declaration of the structure. To solve this use a forward declaration like this

#include "config.h"

struct Config_t;
void somePrintingFunction(struct Config_t* conf);

So the compiler knows what Config is before you use it. Just keep in mind to define all functions that use a predeclared structure or class in the c file because the predeclared object is not a defined one yet but will be in the c file.

EDIT: I should mention that circular inclusion is not a good thing to do and you can usually find another solution which is less sanity risking.