Why aren't my compile guards preventing multiple definition inclusions?

I have a header file x.h which is included by more than one *.c source files. This header file has some structure variables defined.

I have put multiple inclusion prevention guard at the beginning of the header file as:

#ifndef X_H
#define X_H
...
..
//header file declarations and definitons.


#endif//X_H

On building I get linker errors related to multiple definitions. I understand the problem.

  1. Won't a multiple inclusion prevention guard at the top of header file as I have, prevent multiple inclusions of the header file x.h and thereby avoid multiple definitions of the variables that are there in x.h?

  2. #pragma once does not work on this particular compiler, so what is the solution? Someone had posted this answer to a similar question. It doesn't seem to work for me. How does this solution work?


Solution 1:

If the linker is complaining, it means you have definitions rather than just declarations in your header. Here's an example of things that would be wrong.

#ifndef X_H
#define X_H

int myFunc()
{
  return 42; // Wrong! definition in header.
}

int myVar; // Wrong! definition in header.

#endif

You should split this into source and header file like this:

Header:

#ifndef X_H
#define X_H

extern int myFunc();

extern int myVar; 

#endif

C Source:

int myFunc()
{
  return 42; 
}

int myVar; 

Solution 2:

Header guards are only good for a single compilation unit, i.e., source file. If you happen to include a header file multiple times, perhaps because all headers included from main.c in turn include stdio.h then guards will help.

If you have the definition of a function f in x.h which is included by main.c and util.c, then it is like copying and pasting the definition of f into main.c when creating main.o and doing the same for util.c to create util.o. Then the linker will complain and this happens despite your header guards. Having multiple #include "x.h" statements in main.c is possible of course because of these guards.