I have two 2 files:
a.c:
#include <stdio.h>
extern int i = 5;
int main(){
prnt();
}
b.c:
#include <stdio.h>
int i;
void prnt(){
printf("%d",i);
}
The programs compile when linked together using gcc a.c b.c
. The output obtained is 5
. Shouldn't the gcc compiler give an error saying multiple definiton of i
because in a.c, the variable i is both declared and defined and in b.c, the statement int i;
is known to implicitly define the value to 0 with a hidden extern?
Firstly, to avoid confusion, extern int i = 5;
is exactly the same as int i = 5;
. It is a definition because of C11 6.9.2/1:
If the declaration of an identifier for an object has file scope and an initializer, the declaration is an external definition for the identifier.
(Note that "external definition" here means a definition at file scope - not to be confused with "external linkage").
int i;
is called a tentative definition ; in this case it behaves the same as int i = 0;
(this is defined by 6.9.2/2), confirming that it is a definition. It has external linkage because of 6.2.2/5:
If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.
So both of those definitions define i
with external linkage. Section 6.2.2/2 of the C standard says:
[...] each declaration of a particular identifier with external linkage denotes the same object or function.
So both of these i
denote the same object.
From 6.9/5:
If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier
Since you have provided two definitions for i
, your program violates this rule, causing undefined behaviour with no diagnostic required.
The reference for rule violation being undefined behaviour is 4/2:
If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined.
The quoted section from 6.9/5 is a "Semantic:", not a "Constraint:", so it counts as appearing outside of a constraint.