Names either have linkage or they do not. Names with linkage can have either external or internal linkage.
"Linkage" is how the standard refers to the visibility of a name within a translation unit (a "translation unit" is simply the contents of a source file after preprocessing):
[basic.link]
(2.1) — When a name has external linkage , the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.
(2.2) — When a name has internal linkage , the entity it denotes can be referred to by names from other scopes in the same translation unit.
(2.3) — When a name has no linkage , the entity it denotes cannot be referred to by names from other scopes
The linkage of declarations has to match, you are trying to redeclare (and define) a variable previously declared with external linkage as a variable with no linkage.
[dcl.stc]
7 The linkages implied by successive declarations for a given entity shall agree. That is, within a given scope, each declaration declaring the same variable name or the same overloading of a function name shall imply the same linkage. [...]
int main()
{
extern int i; // declare i with external linkage
int i; // define i with no linkage **ERROR**
}
As the standard implies, if the declarations are in different scopes this isn't an issue as they refer to different names:
int main()
{
extern int i; // declare i with external linkage
{
int i; // define i with no linkage (shadows the previous declaration)
}
}
This also works fine at global scope because variables and functions at (non-anonymous) namespace scope without an explicit static
declaration have external linkage:
extern int i; // declare i with external linkage
int i; // define i with external linkage
extern int j; // declare j with external linkage
static int j; // define j with internal linkage **ERROR**
static int k; // define k with internal linkage
extern int k; // declare k with internal linkage (!!)
int main()
{
}
The example with k
is a little counterintuitive: a name declared with extern
will only have external linkage if no previous declarations of the same name exist in the same scope, otherwise the linkage will be unchanged. This isn't an error, unless the name was previously declared with no linkage, which is why you cannot redeclare local variables for instance.
You can find a quick summary of the linkage rules on cppreference.