Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Header/Include guards don't work?

For some reason, I'm getting multiple declarations of content within my header file even though I'm using header guards. My example code is below:

main.c:

#include "thing.h"

int main(){
    printf("%d", increment());

    return 0;
}

thing.c:

#include "thing.h"

int increment(){
    return something++;
}

thing.h:

#ifndef THING_H_
#define THING_H_

#include <stdio.h>

int something = 0;

int increment();

#endif

When I attempt to compile this, GCC says that I have multiple definitions of the something variable. ifndef should make sure that this doesn't happen, so I'm confused why it is.

like image 910
user1007968 Avatar asked Oct 28 '11 07:10

user1007968


People also ask

How do header guards work in C?

Header guards are designed to ensure that the contents of a given header file are not copied more than once into any single file, in order to prevent duplicate definitions.

What is the purpose of an include guard?

In the C and C++ programming languages, an #include guard, sometimes called a macro guard, header guard or file guard, is a particular construct used to avoid the problem of double inclusion when dealing with the include directive.

What is the purpose of header guards in C++?

Header Guards in C++ are conditional compilation directives that help to avoid errors that arise when the same function or variable is defined more than once by the mistake of a programmer. According to C++, when a function or a variable is defined more than once, it yields an error.


3 Answers

The include guards are functioning correctly and are not the source of the problem.

What happens is that every compilation unit that includes thing.h gets its own int something = 0, so the linker complains about multiple definitions.

Here is how you fix this:

thing.c:

#include "thing.h"

int something = 0;

int increment(){
    return something++;
}

thing.h:

#ifndef THING_H_
#define THING_H_

#include <stdio.h>

extern int something;

int increment();

#endif

This way, only thing.c will have an instance of something, and main.c will refer to it.

like image 85
NPE Avatar answered Sep 20 '22 02:09

NPE


You have one definition in each translation unit (one in main.c, and one in thing.c). The header guards stop the header from being included more than once in a single translation unit.

You need to declare something in the header file, and only define it in thing.c, just like the function:

thing.c:

#include "thing.h"

int something = 0;

int increment(void)
{
    return something++;
}

thing.h:

#ifndef THING_H_
#define THING_H_

#include <stdio.h>

extern int something;

int increment(void);

#endif
like image 45
caf Avatar answered Sep 23 '22 02:09

caf


The header guards will stop the file from being compiled more than once in the same compilation unit (file). You are including it in main.c and thing.c, so it will be compiled once in each, leading to the variable something being declared once in each unit, or twice in total.

like image 38
Brian Hooper Avatar answered Sep 20 '22 02:09

Brian Hooper