Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global variables in header file

Tags:

c

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?

like image 700
Bruce Avatar asked Nov 13 '11 00:11

Bruce


People also ask

Can I declare variables in header file?

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.

What happens if we include a static global variable in a header file?

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.

Where should I declare global variables?

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.

Where do you declare global variables in C?

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.


1 Answers

There are 3 scenarios, you describe:

  1. with 2 .c files and with int i; in the header.
  2. With 2 .c files and with int i=100; in the header (or any other value; that doesn't matter).
  3. With 1 .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:

  1. works fine because of the already mentioned "tentative definitions": every .o file contains one of them, so the linker says "ok".

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

  3. works of course, because you have only one .o file and so no possibility for collision.

IMHO a clean thing would be

  • to put either extern int i; or just int i; into the header file,
  • and then to put the "real" definition of i (namely 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.)
like image 200
glglgl Avatar answered Sep 29 '22 22:09

glglgl