I just build a simple C++ project. The codes are shown in the follows:
-------- head.h --------
#ifndef _HEAD_H_
#define _HEAD_H_
int my_var = 100;
#en
Change the header the following way
#ifndef _HEAD_H_
#define _HEAD_H_
extern int my_var;
#endif
And for example add line in the module with main
#include "head.h"
int my_var = 100;
int main() { return 0; }
The problem is that as the header is included in two modules then each module contains a variable with external linkage with the same name as a variable in other module. And the linker does not know which variable to use.
The guard only prevents the header from being included twice in the same compilation unit.
When you compile src1.o
and src2.o
, each one will contain a definition of my_var
. When you link them to create a.out
, the compiler cannot merge those definitions (even if they are identicals), and fails.
What you want to do is declare my_var
as extern :
---- head.h ----
#ifndef _HEAD_H_
#define _HEAD_H_
extern int my_var;
#endif
---- my_var.c ----
#include "head.h"
int my_var = 100;
Then compile all source files :
g++ -c my_var.cpp -o my_var.o
g++ -c src1.cpp -o scr1.o
g++ -c src2.cpp -o src2.o
g++ -o a.out my_var.o src2.o src1.o
This way, my_var
will be declared in every file, but will only be defined in my_var.o
. There is an important difference here. Try to omit linking my_var.o
, you'll see what the compiler has to say :)
You are defining my_var
once per compilation unit. Remember that include guards operate on a per compilation unit basis.
To remedy, you should declare my_var
as extern
in the header:
#ifndef _HEAD_H_
#define _HEAD_H_
extern int my_var;
#endif
and define it in one of the source files using
int my_var = 100;
Then the linker sees only one definition and all will be fine.
your problem boils down to understanding C++ storage classes; static and extern more precisely.
extern says: this variable is defined in a different file, this
is only a declaration
static says: this variable's lifetime is the program lifetime and
restrict it's visibility to the current file.
What happens in your case:
- each file includes the variable declaration and definition `int my_var = 100;`,
so both object scr1.o and scr2.o will contain the variable definition. When
linking them, the linker cannot solve the ambiguity and throws an error.
- adding the extern qualifier and defining the variable in one of the files
solves this problem: in one source it'll be an external unresolved at compile
time, symbol and the other will contain the actual symbol.
As for the second part of your question; why adding static seems to help the linker. Look at what I just said about static storage class: basically each object will have their own copy of the variable - not the same one!