I have three files
File "grandparent.h"
#ifndef GRANDPARENT_H
#define GRANDPARENT_H
struct foo {
int member;
};
#endif /* GRANDPARENT_H */
File "parent.h"
#include "grandparent.h"
File "child.c"
#include "grandparent.h"
#include "parent.h"
Wiki says
Here, the first inclusion of "grandparent.h" causes the macro GRANDPARENT_H to be defined. Then, when "child.c" includes "grandparent.h" the second time, the #ifndef test returns false, and the preprocessor skips down to the #endif, thus avoiding the second definition of struct foo. The program compiles correctly.
q1. "the first inclusion of "grandparent.h" causes the macro
GRANDPARENT_H to be defined", So what i understand i its basically defining a macro named GRANDPARENT_H
but what i dont understand is that how will the content of that macro (i.e GRANDPARENT_H) would be included in the child.c.
We are just defining the macro GRANDPARENT_H i.e
#define GRANDPARENT_H
struct foo {
int member;
};
but how will its content i.e
struct foo {
int member;
};
be included in the child.c
If you "expand" child.c
manually until there are no #include
left:
//grandparent.h
#ifndef GRANDPARENT_H // <- not defined at this point
#define GRANDPARENT_H // <- now it's defined
struct foo {
int member;
};
#endif /* GRANDPARENT_H */
//parent.h
//#include "grandparent.h" resolves into
//grandparent.h
#ifndef GRANDPARENT_H // <- already defined, skip until matching #endif
#define GRANDPARENT_H // <- not executed by preprocessor
struct foo { // <- not provided to the compiler
int member;
};
#endif /* GRANDPARENT_H */
now read it sequentially.
The first line checks if macro GRANDPARENT_H
is defined. Obviously it is not, as it's the first instruction of the code.
The second line defines GRANDPARENT_H
macro. It's empty but that's no important, what's important is that it is defined.
Then, the code defines your struct...
When the preprocessor encounters the second #ifdef GRANDPARENT_H
, the macro is already defined, so it skips the whole contents of the file and you don't get any foo redefined
error.
Which is confirmed by using -E
option to see preprocessed child.c
file:
$ gcc -E child.c
# 1 "child.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "child.c"
# 1 "grandparent.h" 1
struct foo {
int member;
};
# 2 "child.c" 2
# 1 "parent.h" 1
# 2 "child.c" 2
as you can see, the structure is only defined once.
Note that most compilers now support a simpler way to do this: just insert
#pragma once
at the start of your file. Like this:
#pragma once
struct foo {
int member;
};
that's it!