Examples of each:
External linkage:
foo.h
extern int foo; // Declaration
foo.cpp
extern int foo = 42; // Definition
bar.cpp
#include "foo.h"
int bar() { return foo; } // Use
Internal linkage:
foo.cpp
static int foo = 42; // No relation to foo in bar.cpp
bar.cpp
static int foo = -43; // No relation to foo in foo.cpp
No linkage:
foo.cpp
int foo1() { static int foo = 42; foo++; return foo; }
int foo2() { static int foo = -43; foo++; return foo; }
Surely you will agree that the foo
variables in functions foo1
and foo2
have to have storage. This means they probably have to have names because of how assemblers and linkers work. Those names cannot conflict and should not be accessible by any other code. The way the C++ standard encodes this is as "no linkage." There are a few other cases where it is used as well, but for things where it is a little less obvious what the storage is used for. (E.g. for class
you can imagine the vtable has storage, but for a typedef
it is mostly a matter of language specification minutiae about access scope of the name.)
C++ specifies somewhat of a least common denominator linkage model that can be mapped onto the richer models of actual linkers on actual platforms. In practice this is highly imperfect and lots of real systems end up using attributes, pragmas, or compiler flags to gain greater control of linkage type. In order to do this and still provide a reasonably useful language, one gets into name mangling and other compiler techniques. If C++ were ever to try and provide a greater degree of compiled code interop, such as Java or .NET virtual machines do, it is very likely the language would gain clearer and more elaborate control over linkage.
EDIT: To more clearly answer the question... The standard has to define how this works for both access to identifiers in the source language and linkage of compiled code. The definition must be strong enough so that correctly written code never produces errors for things being undefined or multiply defined. There are certainly better ways to do this than C++ uses, but it is largely an evolved language and the specification is somewhat influenced by the substrate it is compiled onto. In effect the three different types of linkage are:
- External linkage: The entire program agrees on this name and it can be access anywhere there is a declaration visible.
- Internal linkage: A single file agrees on this name and it can be accessed in any scope the declaration is visible.
- No linkage: The name is for one scope only and can only be accessed within this scope.
In the assembly, these tend to map into a global declaration, a file local declaration, and a file local declaration with a synthesized unique name.
It is also relevant for cases where the same name is declared with different linkage in different parts of the program and in determining what extern int foo
refers to from a given place.