Reputation: 3042
I am confused as why the following works:
test.c
#include <stdio.h>
int g;
// ??? should be extern int g; ???
int main(){
printf("%i\n", g);
return 0;
}
lib.c
int g = 3;
Why am I not getting a duplicate symbol error upon compilation? I get the error while trying to do this in C++, so that satisfies me. However, in this example, everything compiles and works (i.e. prints 3 successfully) whether or not I include extern. From reading all the other questions on StackOverflow about extern in C, everyone seems to be saying that extern used on a variable declares the variable but does not define (i.e. allocate memory) for it. But here, if I don't use extern, then I am defining two separate variables, both called g, so there should be some kind of duplicate symbol error. But there isn't, so I am very confused.
Upvotes: 1
Views: 166
Reputation: 16107
N1570, 6.9.2 (Emphasis mine):
2 A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition.
4 EXAMPLE 1
int i1 = 1; // definition, external linkage static int i2 = 2; // definition, internal linkage extern int i3 = 3; // definition, external linkage int i4; // tentative definition, external linkage static int i5; // tentative definition, internal linkage int i1; // valid tentative definition, refers to previous int i2; // 6.2.2 renders undefined, linkage disagreement int i3; // valid tentative definition, refers to previous int i4; // valid tentative definition, refers to previous int i5; // 6.2.2 renders undefined, linkage disagreement extern int i1; // refers to previous, whose linkage is external extern int i2; // refers to previous, whose linkage is internal extern int i3; // refers to previous, whose linkage is external extern int i4; // refers to previous, whose linkage is external extern int i5; // refers to previous, whose linkage is internal
The int g;
in your "test.c" is a tentative definition, giving g
external linkage (See the examples). However, int g = 3;
in "lib.c" has an initialiser, so it's not a tentative definition. As a result, the g
in "test.c" refers to the g
in "lib.c", whose value is initialised to 3.
See also: http://en.cppreference.com/w/c/language/extern
Upvotes: 1