Header Guards in C++ and C

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

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.

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++ Header Guard Syntax and Header Placement

You should not write the header guard in source code (.cpp) file.

We should avoid the double header guard as well The use of double include guards in C++

Header guard is to avoid multiple time inclusion of header file during compilation of code.

Also, while adding the #include file, keep in mind that we should not add the unwanted files there.
e.g.
Consider case if source file requires to #include <iostream> but you included in header file then this should be avoided. Such case #include <iostream> in source file only.

#pragma once is supported by many compilers but it's not language standard and it do not guarantee when file are referenced from remote location and different disks.

c header-guards are ignored?

Header guards guard against multiple inclusion in a single translation unit (usually a .c file and everything it includes, directly or indirectly).

You have two translation units, main.c and source.c, and they're compiled independently (even if you use a single command line line gcc main.c source.c). That's why you're getting an error message from the linker, not from the compiler.

If you want to define an object, you should do it in a .c file and declare it as extern in the corresponding .h file. The .c file defining the object is compiled just once, and multiple other .c files can see the declaration in the .h file.

Include guard conventions in C

Does underscore convention matter?

Yes. It matters.

Identifiers with a leading underscore followed upper case letter is reserved for implementation. So what you have would cause undefined behaviour.

The following is the C standard's specification for naming the identifiers (C11 draft):

7.1.3 Reserved identifiers

Each header declares or defines all identifiers listed in its
associated subclause, and optionally declares or defines identifiers
listed in its associated future library directions subclause and
identifiers which are always reserved either for any use or for use as
file scope identifiers.

— All identifiers that begin with an underscore and either an
uppercase letter or another underscore are always reserved for any
use.

— All identifiers that begin with an underscore are always reserved
for use as identifiers with file scope in both the ordinary and tag
name spaces.

— Each macro name in any of the following subclauses (including the
future library directions) is reserved for use as specified if any of
its associated headers is included; unless explicitly stated otherwise
(see 7.1.4). — All identifiers with external linkage in any of the
following subclauses (including the future library directions) and
errno are always reserved for use as identifiers with external
linkage.184) — Each identifier with file scope listed in any of the
following subclauses (including the future library directions) is
reserved for use as a macro name and as an identifier with file scope
in the same name space if any of its associated headers is included.

No other identifiers are reserved. If the program declares or defines
an identifier in a context in which it is reserved (other than as
allowed by 7.1.4), or defines a reserved identifier as a macro name,
the behavior is undefined.

If the program removes (with #undef) any macro definition of an
identifier in the first group listed above, the behavior is undefined.

Without violating any of the above, the include guard name can be anything and doesn't have to be the name of the header file. But usually the convention I have seen/used is to use same name as that of the header file name so that it doesn't cause any unnecessary confusion.

C Header include-guards used only in header files but not in .c files. Why?

What the header guards are doing is not to prevent multiple inclusion in a project, but in a single translation unit only.

For example, lets say you have two header files, a.h and b.h. The header file b.h includes a.h, and then both a.h and b.h is included in the source file s.c. Without header guards the file a.h will be included twice, which can cause errors. If the header files had header guards then the file a.h would only be included once.

You don't need header guards in source files because usually you don't include them in other files.



Related Topics



Leave a reply



Submit