C++ #Include Guards

What exactly do C include guards do?

It's a preprocessor macro.

All of it is preprocessor syntax, that basically says, if this macro has not already been defined, define it and include all code between the #ifndef and #endif

What it accomplishes is preventing the inclusion of file more than once, which can lead to problems in your code.

Your question:

And why is it okay to forget the include guard in which case we can also forgot adding #define HEADER_FILE?

It's OK to forget it because it's still legal C code without it. The preprocessor processes your file before it's compiled and includes the specified code in your final program if there's no logic specifying why it shouldn't. It's simply a common practice, but it's not required.

A simple example might help illustrate how this works:

Your header file, header_file.h we'll say, contains this:

#ifndef HEADER_FILE
#define HEADER_FILE

int two(void){
return 2;
}

#endif

In another file (foo.c), you might have:

#include "header_file.h"

void foo() {
int value = two();
printf("foo value=%d\n", value);
}

What this will translate to once it's "preprocessed" and ready for compilation is this:

int two(void){
return 2;
}

void foo() {
int value = two();
printf("foo value=%d\n", value);
}

All the include guard is accomplishing here is determining whether or not the header contents between the #ifndef ... and #endif should be pasted in place of the original #include.

However, since that function is not declared extern or static, and is actually implemented in a header file, you'd have a problem if you tried to use it in another source file, since the function definition would not be included.

C: Extern variable declaration and include guards

Include guards are useful for preventing multiple delcarations or type definitions in a single translation unit, i.e. a .c file that is compiled by itself along with all of the headers it includes.

Suppose you have the following headers without include guards:

a.h:

struct test {
int i;
};

struct test t1;

b.h:

#include "a.h"

struct test *get_struct(void);

And the following main file:

main.c:

#include <stdio.h>
#include "a.h"
#include "b.h"

int main()
{
struct test *t = get_struct();
printf("t->i=%d\n", t->i);
return 0;
}

When the preprocessor runs on the, the resulting file will look something like this (neglecting the contents of stdio.h):

struct test {
int i;
};

struct test t1;

struct test {
int i;
};

struct test t1;

struct test *get_struct(void);

int main()
{
struct test *t = get_struct();
printf("t->i=%d\n", t->i);
return 0;
}

Because main.c includes a.h and b.h, and because b.h also includes a.h, the contents of a.h appear twice. This causes struct test to be defined twice which is an error. There is no problem however with the variable t1 because each constitutes a tentative definition, and multiple tentative definitions in a translation unit are combined to refer to a single object defined in the resulting main.o.

By adding include guards to a.h:

#ifndef A_H
#define A_H

struct test {
int i;
};

struct test t1;

#endif

The resulting preprocessor output would be:

struct test {
int i;
};

struct test *get_struct(void);

int main()
{
struct test *t = get_struct();
printf("t->i=%d\n", t->i);
return 0;
}

Preventing the duplicate struct definition.

But now let's look at b.c which constitutes a separate translation unit:

b.c:

#include "b.h"

struct test *get_struct(void)
{
return &t1;
}

After the preprocessor runs we have:

struct test {
int i;
};

struct test t1;

struct test *get_struct(void);

struct test *get_struct(void)
{
return &t1;
}

This file will compile fine since there is one definition of struct test and a tentative definition of t1 gives us an object defined in b.o.

Now we link a.o and b.o. The linker sees that both a.o and b.o contain an object called t1, so the linking fails because it was defined multiple times.

Note here that while the include guards prevent a definition from appearing more than once in a single translation unit, it doesn't prevent it from happening across multiple translation units.

This is why t1 should have an external declaration in a.h:

extern struct test t1;

And a non-extern declaration in one .c file.

Include Guards in C

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.)

C Issue with include guards

#ifndef __BST_INCLUDED
#define __BST_INCLUDED__
//bunch of code here
#endif

This will not protect anything. For the simple reason that __BST_INCLUDED__ is not the same as __BST_INCLUDED, and __BST_INCLUDED never gets defined.

But also:

bst.h:22:13: error: conflicting types for ‘pruneBSTNode’
extern void pruneBSTNode(bst *tree,bstNode *node);
^
In file included from vbst.h:5:0,
from bstrees.c:7:

this error is not telling you that "the function has been included from another file", it's a completely unrelated error. The "included from" part is just telling you how the compiler got to the line displayed after it (which is missing from the question).

c++ include guards don't work, error

Include guards guard from a header file being included twice in a single file but here you have two different files. My advice is not to define any variables in header files. Instead declare them as extern and define them in a separate cpp file where you include you header file. This way you will have only one definition but you will have them declared where you use them.

C language, proper usage of include guards

Include guards are used to prevent double definition in case an include file get included more than once.

The standard include files have the necessary include guards, so you need no include guards for them.

Your code should be:

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

The use of double include guards in C++

I am pretty sure that it is a bad practice to add another include guard like:

#ifndef __HEADER_A_HPP__
#include "header_a.hpp"
#endif

Here are some reasons why:

  1. To avoid double inclusion it is enough to add a usual include guard inside the header file itself. It does the job well. Another include guard in the place of inclusion just messes the code and reduces readability.

  2. It adds unnecessary dependencies. If you change include guard inside the header file you have to change it in all places where the header is included.

  3. It is definitely not the most expensive operation comparing the whole compilation/linkage process so it can hardly reduce the total build time.

  4. Any compiler worth anything already optimizes file-wide include-guards.



Related Topics



Leave a reply



Submit