I've had the same problem as described in these two posts (First and Second) regarding declaration of variables in header files. The solution listed works well for me, but nonetheless I have a basic question on the solution:
Why would an include guard still not solve this issue? I would expect that the include guard would avoid my variable to be declared multiple times if I include the same header file multiple times.
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:
b.h:
And the following main file:
main.c:
When the preprocessor runs on the, the resulting file will look something like this (neglecting the contents of stdio.h):
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 testto be defined twice which is an error. There is no problem however with the variablet1because 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:
The resulting preprocessor output would be:
Preventing the duplicate struct definition.
But now let's look at b.c which constitutes a separate translation unit:
b.c:
After the preprocessor runs we have:
This file will compile fine since there is one definition of
struct testand a tentative definition oft1gives 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
t1should have an external declaration in a.h:And a non-extern declaration in one .c file.