Search code examples
cincludeheader-files

C - Duplicate symbol if put include in header, but works fine if include in source file


I have a header file that contains an array of int

primes.h

#ifndef P_H
#define P_H
#include <inttypes.h>

uint64_t primes[] = {
    7,
    11,
};
#endif

in lib.h file: #include "primes.h"

lib.c includes lib.h

in main.c file: #include "lib.h"

Then it causes error: duplicate symbol '_primes' in:

But if i move #include "primes.h" into lib.c, it works fine. Why putting include in source and header can make the difference?


Solution

  • When you include a file, the include is replaced with the file contents (and this continues until there are no more includes).

    • If main.c and lib.c both include lib.h, then they both have separate copies of lib.h compiled in.
    • If lib.h includes primes.h, then they both have their own separate copies of primes.h compiled in.
    • If primes.h has an array defined, then they both have a copy of that array.
    • And if they both have anything with the same name defined in both files, you get a duplicate definition error.

    The best way to fix this is to only have 1 definition of the primes array with all of its values in a source file (e.g. lib.c), and you need to use the extern keyword in primes.h with no values to declare that one of your files contains the actual array (you can leave the size unspecified in this case). Note that this use of the extern keyword is a sort of promise to the compiler that there is some file containing the actual array, and that's why you still need the actual array in a source file:

    // primes.h
    extern uint64_t primes[];
    
    // lib.c
    #include "primes.h"
    uint64_t primes[] = {
        7,
        11,
    };
    
    // main.c
    #include "primes.h"