I have a 2 modules (.c files) and one .h header file:
file1.c:
#include <stdio.h> #include "global.h" int main() { i = 100; printf("%d\n",i); foo(); return 0; }
file2.c
#include <stdio.h> #include "global.h" void foo() { i = 10; printf("%d\n",i); }
global.h
int i; extern void foo()
When I do gcc file1.c file2.c everything works fine and I get the expected output. Now, when I initialize variable 'i' in the header file to say 0 and compile again I get a linker error:
/tmp/cc0oj7yA.o:(.bss+0x0): multiple definition of `i' /tmp/cckd7TTI.o:(.bss+0x0): first defined here
If I just compile file1.c (removing call to foo()) with the initialization in the header file i.e. gcc file1.c, everything works fine. What is going on?
Yes. Although this is not necessarily recommended, it can be easily accomplished with the correct set of macros and a header file. Typically, you should declare variables in C files and create extern definitions for them in header files.
Basically, each source file together with all included header files is a single translation unit. So If you have a static variable in a header file then it will be unique in each source file (translation unit) the header file is included in.
If you intend to use the global variables in multiple . c files, it is better to declare them in . h files. However, if you want to keep the variables like private member data of classes in C++, it will be better to provide access to the global data through functions.
The C compiler recognizes a variable as global, as opposed to local, because its declaration is located outside the scope of any of the functions making up the program. Of course, a global variable can only be used in an executable statement after it has been declared.
There are 3 scenarios, you describe:
.c
files and with int i;
in the header..c
files and with int i=100;
in the header (or any other value; that doesn't matter)..c
file and with int i=100;
in the header.In each scenario, imagine the contents of the header file inserted into the .c
file and this .c
file compiled into a .o
file and then these linked together.
Then following happens:
works fine because of the already mentioned "tentative definitions": every .o
file contains one of them, so the linker says "ok".
doesn't work, because both .o
files contain a definition with a value, which collide (even if they have the same value) - there may be only one with any given name in all .o
files which are linked together at a given time.
works of course, because you have only one .o
file and so no possibility for collision.
IMHO a clean thing would be
extern int i;
or just int i;
into the header file,int i = 100;
) into file1.c
. In this case, this initialization gets used at the start of the program and the corresponding line in main()
can be omitted. (Besides, I hope the naming is only an example; please don't name any global variables as i
in real programs.)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With