0

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

7
  • 2
    it has no value. It's just defined to ensure that the types & functions definitions just are evaluated once by the compiler. Commented Jan 23, 2018 at 12:23
  • @Jean-FrançoisFabre do you mean that the macro GRANDPARENT_H is empty Commented Jan 23, 2018 at 12:24
  • 2
    Just run gcc -E to get the code after preprocessor has done its thing, check the documentation for the compiler you're using if not gcc. Clang uses the same -E flag it seems (clang.llvm.org/docs/CommandGuide/clang.html) Commented Jan 23, 2018 at 12:26
  • 1
    @rimiro you can write #define FOO 123. Then the preprocesseur symbol FOO is defined and each time you write FOO, FOO will be replaced by 123. But you can also write #define FOO. Then the preprocesseur symbol FOOis also defined and each time you write FOO, FOO will be replaced by, you've guessed it, an empty string. Commented Jan 23, 2018 at 12:30
  • 1
    The content of the macro is only what's beyond it on its line, not the file content. Commented Jan 23, 2018 at 12:31

1 Answer 1

3

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!

Sign up to request clarification or add additional context in comments.

2 Comments

So when we write #define GRANDPARENT_H we are defining a empty macro and it has nothing to do with the line below it?? Please answer this thats the last thing confusing me
@rimiro yes that's it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.