Header Guards or Include Guards

What is Preprocessing ? 


Firstly, #include <file.h> in .c files instructs the preprocessor to process the file and insert the result into the output.

Every .c file will be processed through preprocessor and will generate preprocessed code. This preprocessed code will be the input for compiler to create object file. Header files include only the declarations and not the definitions.  




In the above diagram, there is only one .c and .h as source code. But we will be having more source codes which will be the input to preprocessor. Click here to learn Makefile. 


      vicky.c                      rose.h      shirley.c    shirley.h     vicky.h   
            \                         /            \          \            |            /
             \                       /                \         \          |         /
               \                    /                   \        \         |      /
                preprocessor                      preprocessor 
                        |                                             |
                        |                                             | 
             preprocessed code             preprocessed code 
                        |                                             |
                 Compiler                               Compiler
                        |                                             |
                        |                                             |
               Object Code                          Object Code
                                 \                          /
                                   \                      /
                                     \                  /
                                       \              /
                                          Linker
                                              |
                                              |
                                     Executable Code (binary)

A translation unit roughly consists of a source file after it has been processed by the C preprocessor, meaning that header files listed in #include directives are literally included, sections of code within #ifndef may be included, and macros have been expanded.

For example, if you have the source files foo.cpp and bar.cpp, they can be placed in a Single Compilation Unit as follows:

#include "foo.cpp"
#include "bar.cpp"

Suppose foo.cpp and bar.cpp are:

//foo.cpp
#include <iostream> // A large, standard header
#include "bar.h"    // Declaration of function 'bar'

int main()          // Definition of function 'main'
{ 
  bar();
}
//bar.cpp
#include <iostream> // The same large, standard header

void bar()          // Definition of function 'bar'
{
  ...
}
Preprocessed code contains only the declarations and not definitions. Compiler will add the symbol table for anything that is missing definitions. 

The linker conflates the object files. It matches up the definitions with the references to the symbol table. If two object files provide same definition, and the linker will take one. This occurs if the executables are added in your headers.  

Though the declarations or definitions present multiple times across all object files, linker ensures that it is only present once in the executable.

Click here to know about why header files are needed.

What is Header Guard ? 


1) Header guards will ensure the contents of each header file are present at most once in the preprocessed code for a translation unit. 

2) A preprocessor statement that prevents a source file from being included more than once in a project

3) In other words, Header Guards are provisions to counter erroneous multiple inclusions. 

In every .h file, we will have preprocessor directive like below.

#ifndef CRAFT_H                                                
#define CRAFT_H                                                
                                                                              
#endif                                                                    

The above is the include guard for header file craft.h

CRAFT_H is undefined for the first time and preprocessor will assess the contents within the define and endif block. But if the .h file included again, it will skip this block for the second time. So, the definitions will be included only once.

These are also called as "Protective define"

Why Header Guard ? 

Without header guard, we might include twice the same .h file and it would throw the below kind of errors.

error: redeclaration of ‘enum shir’

Example Problem

sample.c                   |   shirley.h          |     rose.h 
                           |                      |
#include<stdio.h>          |   #include"rose.h"   |    enum shir {
#include "shirley.h"       |                      |             i = 0,
#include "rose.h"          |                      |             j,
                           |                      |    };

In the above example, sample.c includes "shirley.h" and "rose.h" and "shirley.h" includes "rose.h". Finally the preprocessed code will have "rose.h" twice. To avoid this problem, header guards are added. But ensure the header guard name is unique in each file. Else we will end up missing remarkable .h files. 

Example Problem

sample.c                   |   shirley.h               |     rose.h 
                           |                           | 
#include<stdio.h>          |   #ifndef  _SHIRLEY_H     |   #ifndef  _SHIRLEY_H
#include "shirley.h"       |   #define _SHIRLEY_H      |   #define _SHIRLEY_H         
#include "rose.h"          |   int start_arr_ind = 5;  |    void store_index_val(int arr[]);     
                           |   #endif                  |    #endif
In this above case, sample.c included two header files "shirley.h" and "rose.h" but contents of rose.h are not included, because header guard protected rose.h contents being added again as it has the same header guard name.

Sources : Various websites and stackoverflow 

Comments