Linkage in C and C++

March 03, 2008

Dan_Saks-March 03, 2008

A name declared in C or C++ may have attributes such as type, scope, storage duration, and linkage. Not every name has all of these attributes. For example, a function name has a type, a scope, and a linkage, but no storage duration. A statement label name has only a scope.

An object's type determines the object's size and memory address alignment, the values the object can have, and the operations that can be performed on that object. A function's type specifies the function's parameter list and return type.

A name's scope is that portion of a translation unit in which the name is visible.1 (A translation unit is the source code produced by the preprocessor from a source file and all its included headers.) C supports four different kinds of scope: file scope, block scope, function prototype scope, and function scope. C++ generalizes file scope into namespace scope, and adds class scope.

An object's storage duration determines the lifetime of the storage for that object.2 That is, it determines how and when during program execution the storage for that object comes and goes. Each object in C and C++ has one of the following three storage durations: static, automatic, and dynamic. Only objects have storage duration. Enumeration constants, functions, labels, and types don't.

Which brings us to linkage. A name's linkage affects whether two or more declarations for that name are valid, and if so, whether they refer to the same entity (such as a function or an object). Understanding linkage clears up a number of misconceptions about the behavior of C and C++ programs.

In my earlier article on the scope rules,1 I explained the distinction between declarations and definitions, but omitted some details. Those details are pertinent to the concept of linkage, so let's take a look at them first.

A declaration associates attributes with names. A declaration either introduces a name into the current translation unit or redeclares a name introduced by a declaration that appeared earlier in the same translation unit. A declaration for a name might also be a definition. Informally, a definition is a declaration that not only says "here's a name," but also "here's all the information the compiler needs to create the code for that name".

C++ lets you declare all sorts of things that aren't valid in C, such as classes, namespaces, and linkage specifications. Not surprisingly, these features make the distinction between definitions and other declarations, as well as the linkage rules, more complicated in C++ than in C. However, we don't really need to consider all those features to explain linkage--using just functions and objects should provide adequate illustration.

For function declarations that are valid in both C and C++, the rule for deciding when a function declaration is also a definition is the same for both languages, namely, that a function declaration is also a function definition if it includes a brace-enclosed body, as in:

int abs(int v)
    return v < 0 ? -v : v;

A function heading without a body, as in:

int abs(int v);

is just a declaration.

For object declarations that are valid in both C and C++, the rule for deciding when an object declaration is also a definition is--surprisingly--simpler in C++ than in C. In C++, an object declaration is also a definition unless it contains an extern specifier and no initializer.

For example, all of the following object declarations are also definitions in C++:

int i;                 // definition
static int j;          // definition
extern int k = 0;      // definition

They are definitions whether they appear at file scope, namespace scope, or block scope.

The following object declaration is not a definition:

extern int m;          // non-defining declaration

< Previous
Page 1 of 5
Next >

Loading comments...