Linkage
In programming languages, particularly the compiled ones like C, C++, and D, linkage describes how names (that is, symbols) can or can not refer to the same entity throughout the whole program or one single translation unit.
The static keyword is used in C to restrict the visibility of a function or variable to its translation unit. This is also valid in C++. (C++ 98/03 deprecated this usage in favor of anonymous namespaces, but is no longer deprecated in C++ 11.) Also, C++ implicitly treats any const namespace-scope variable as having internal linkage unless it is explicitly declared extern, unlike C.
A name's linkage is related to, but distinct from, its scope. The scope of a name is the part of a translation unit where it is visible. For instance, a name with global scope (which is the same as file-scope in C and the same as the global namespace-scope in C++) is visible in any part of the file. Its scope will end at the end of the translation unit, whether or not that name has been given external or internal linkage.
If the name has external linkage, the entity that name denotes may be referred to from another translation unit using a distinct declaration for that same name, and from other scopes within the same translation unit using distinct declarations. Were the name given internal linkage, such a declaration would denote a distinct entity, although using the same name, but its entity could be referred to by distinct declarations within the same translation unit. A name that has no linkage at all cannot be referred to from declarations in different scopes, not even from within the same translation unit. Examples of such names are parameters of functions and local variables. The details differ between C (where only objects and functions - but not types - have linkage) and C++ and between this simplified overview.
Linkage between languages must be done with some care, as different languages adorn their external symbols differently. A common idiom uses extern "C" to link C++ and C code.
Linkage in C
Definition of linkage
quoted from ISO/IEC 9899:TC3 (C99 Standard). C uses the term identifier
where this page uses name
(the latter of which is what C++ uses to formalize linkage):
An identifier declared in different scopes or in the same scope more than once can be made to refer to the same object or function by a process called linkage.
The following is a common example of linkage:
/* file demo1.c */
/* extern */ void foo(void); /* extern optional - it's the default */
int main(void)
{
foo();
return 0;
}
and
/* file demo2.c */
void foo(void)
{
...
}
Function foo is declared in two files, with its function body defined in demo2.c. Via linkage, foo called in main() inside demo1.c refers to foo in demo2.c. This is an example of external linkage for a function.
Linkage is a process that controls whether an interface is public or private and determines whether any two identifiers refer to the same entity. Ignoring macros and macro parameters that are replaced early in the translation phases, an identifier can denote a standard attribute, an attribute prefix, or an attribute name; an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; or a label name.
C provides three kinds of linkage: external, internal, or none. Each declaration of an identifier with external linkage refers to the same function or object everywhere in the program. Identifiers referring to declarations with internal linkage refer to the same entity only within the translation unit containing the declaration. If two translation units both refer to the same internal linkage identifier, they refer to different instances of the entity. If a declaration has no linkage, it’s a unique entity in each translation unit.
The linkage of a declaration is either explicitly declared or implied. If you declare an entity at file scope without explicitly specifying extern or static, the entity is implicitly given external linkage. Identifiers that have no linkage include function parameters, block scope identifiers declared without an extern storage class specifier, or enumeration constants.
The following listing shows examples of declarations of each kind of linkage:
static int i; // i has explicit internal linkage
extern void foo(int j) {
// foo has explicit external linkage
// j has no linkage because it is a parameter
}
If you explicitly declare an identifier with the static storage class specifier at file scope, it has internal linkage. The static keyword gives internal linkage only to file scope entities. Declaring a variable at block scope as static creates an identifier with no linkage, but it does give the variable static storage duration. As a reminder, static storage duration means its lifetime is the entire execution of the program, and its stored value is initialized only once, prior to program startup. The different meanings of static when used in different contexts are obviously confusing and consequently a common interview question.
You can create an identifier with external linkage by declaring it with the extern storage class specifier. This works only if you haven’t previously declared the linkage for that identifier. The extern storage class specifier has no effect if a prior declaration gave the identifier linkage.
Declarations with conflicting linkage can lead to undefined behavior; see CERT C rule DCL36-C, Do not declare an identifier with conflicting linkage classifications,
for more information.
The following listing shows sample declarations with implicit linkage:
void func(int i) {// implicit external linkage
// i has no linkage
}
static void bar(); // internal linkage, different bar from bar.c
extern void bar() {
// bar still has internal linkage because the initial declaration
// was declared as static; this extern specifier has no effect
}
The following listing shows sample declarations with explicit linkage:
extern void func(int i); // explicit external linkage
static void bar() { // internal linkage; different bar from foo.c
func(12); // calls func from foo.c
}
int i; // external linkage; doesn’t conflict with i from foo.c or bar.c
void baz(int k) {// implicit external linkage
bar(); // calls bar from bar.c, not foo.c
}
The identifiers in your public interface should have external linkage so that they can be called from outside their translation unit. Identifiers that are implementation details should be declared with internal or no linkage (provided they don’t need to be referenced from another translation unit). A common approach to achieving this is to declare your public interface functions in a header with or without using the extern storage class specifier (the declarations implicitly have external linkage, but there is no harm in explicitly declaring them with extern) and define the public interface functions in a source file in a similar manner.
However, within the source file, all declarations that are implementation details should be explicitly declared static to keep them private—accessible to just that source file. You can include the public interface declared within the header by using the #include preprocessor directive to access its interface from another file. A good rule of thumb is that file-scope entities that don’t need to be visible outside the file should be declared as static. This practice limits the global namespace pollution and decreases the chances of surprising interactions between translation units.