Search code examples
c++cheaderinclude-guards

Why do include guards not prevent linker errors?


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.


Solution

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