I'm trying to understand the usage of extern and global variable declaration in header files so I came up with the following test program written in C.
The main.c file
//main.c
#include "global.h"
#include <stdio.h>
int nExternValue = 6;
int main(int argc, char* argv[])
{
printf("%d \n", nValue);
printf("%d \n", nExternValue);
AddToValue();
printf("%d \n", nValue);
printf("%d \n", nExternValue);
}
The global.h file
#ifndef _GLOBAL_H
#define _GLOBAL_H
//WRONG! do not declare a variable here
int nValue;
//OK! extern variable makes it a global accessable variable
extern int nExternValue;
//OK! function prototype can be placed in h file
int AddToValue();
#endif
and a AddValue.c file which implements the AddToValue function.
#include "global.h"
int AddToValue() {
nValue++;
nExternValue++;
}
I compiled the app using gcc, AND ran it:
$ gcc main.c AddValue.c -o test
$./test
0
6
1
7
I complied the app using g++ and got the following linker error:
$ g++ main.c AddValue.c -o test
/tmp/ccFyGDYM.o:(.bss+0x0): multiple definition of `nValue'
/tmp/cc3ixXdu.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status
Why doesn't the gcc linker produce an error? I though the nValue variable would be declared multiple times and that would produce an error!
$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
C and C++ are different languages. Case in point, the above program is a valid C program but in ill-formed C++ program. You have violated C++'s one definition rule. There is no corresponding rule in C.
When compiling with gcc, you are compiling the above text as a C program. When compiling with g++, you are compiling the above text as a C++ program.
When compiled with gcc, uninitialized global variable (such as nValue) will be treated as a common symbol. The same common symbol occurred in different compilation unit will be merged during link time. If compiled with g++ (which means that the source program will be treated as C++ program), uninitialized global variable are implicitly initialized with a default value 0. Since global.h is included in multiple source files, the compiler will consider the symbol nValue defined multiple times.
Please also have a look at this post: Why uninitialized global variable is weak symbol?
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