The meaning of extern
is a bit complicated because C was developed over time by different people trying different things, rather than being designed from the start with knowledge of what the end product should be.
The reason extern int x=4;
inside a block is an error is it violates this rule in C 2018 6.7.9 5:
If the declaration of an identifier has block scope, and the identifier has external or internal linkage, the declaration shall have no initializer for the identifier.
I am not sure what the exact motivation for that rule is. One motivation might be, “The compiler is busy defining a function here, and defining another thing at the same time is unexpected, awkward, or difficult for the compiler.” I am not sure it would actually be difficult to implement, but maybe it could be a problem for some compilers, especially early compilers way back when.
A reason for the warning is that we usually use extern
with declarations to say “We are only declaring this identifier to tell you about an object defined somewhere else.” That is a matter of common practice, not a rule.1 But the initialization says “We are defining an object here.” So that is a contrast, and the compiler warns you about it. However, it is not an actual rule violation, so the compiler does not report it as an error.
Footnote
1 There are rules that fit this practice. At file scope, int x;
is a tentative definition, whereas extern int x;
is a declaration that is not a definition. So that comports with the practice; extern int x;
says we are just declaring x
, whereas int x;
says we might be defining it. However, int x = 4;
and extern int x = 4;
are both definitions and do not violate any rule.