Previous Table of Contents Next


3.2.6. Scope, Duration, Linkage, and Storage Classes

An extra keyword, called the storage-class, can be added to a declaration (usually at the beginning) in order to control certain aspects of a variable’s scope, duration, and linkage. To illustrate the use of storage classes, we must first look at how scope, duration, and linkage work in the absence of storage classes.

The scope or visibility of a variable’s identifier is controlled by the placement of the variable’s declaration. Variables declared within a function (or more locally, within a block; see section 4) have local scope, and are visible only within that function (or block). Variables declared outside of any function, on the other hand, have some degree of global scope, and are potentially visible to many functions.

The duration or lifetime of a variable determines when storage for it is allocated and deallocated. By default, local variables have automatic duration. This means that they spring into existence when the function containing them is called and disappear when the function returns. Variables declared outside functions, however, have static duration: They are created when the program is first invoked, and persist until the program terminates.

The automatic allocation of local variables means that if a function is called recursively, each invocation is allocated its own copies of all local variables, which therefore do not conflict with each other. Because automatic variables disappear when the containing function returns, they do not retain their values from call to call.

Global variables (and functions) can be used in programs that are built from multiple source files. A global variable or function may be referenced, via an external declaration, from many places in potentially many source files, but it must have exactly one defining instance, in exactly one source file. The term linkage refers to the process of matching up the references to global variables and functions, wherever they may appear, with their unique definitions.

All of the preceding attributes of a declaration may be modified by means of the storage-class specifier. The first storage-class to discuss is static, which has two different uses. When used in a declaration of a variable outside any function (an otherwise global variable), it limits the scope of that variable to the source file in which it is declared, and prevents it from being accessed from other source files. By default, outside a function, a declaration like

int globalvar;

declares a truly global variable that can potentially be accessed from any source file. With the addition of the keyword static, however,

static int privatevar;

the declaration is of a variable that, though global to its source file and accessible to any function in that source file, is not accessible to any function in any other source file. Functions can also be declared with the storage-class static, with the same result: A static function becomes private to its containing source file.

The second use of the storage-class specifier static is in controlling the duration of local variables. Inside a function, as mentioned, a declaration is by default of a variable with local scope and automatic duration. With the addition of the keyword static, however, the variable achieves static duration, meaning that it does not come and go as the function is called and returns, and that it does not lose its value between invocations of the function. Instead, it is created just once, when the program begins execution, and lasts as long as the program does. (This also means that one copy of the variable is shared among any recursive invocations of the function. See section 3.5.3 for a realistic example.)

The storage-class specifier extern is used in distinguishing between defining instances and external declarations of global variables and functions. Roughly speaking, a declaration not containing the storage-class extern is a defining instance, and a declaration with the storage-class extern is an external declaration. Section 3.5.4 discusses these two forms of declarations in more detail.

So far, we have mentioned two storage-class specifiers, static and extern. There are five storage-class specifiers in all, summarized here:

  static—For a variable declared outside any function, or for a function, indicates that the variable or function is to be private to the containing source file. For a local variable, indicates that the variable is to have static duration.
  extern—Indicates (with one exception) that a declaration is an external declaration of a variable or function defined elsewhere. (The exception is that a declaration containing an explicit initializer is a defining instance even if it contains the storage-class extern, although there is little use to be made of this exception.)
  register— For a local variable or function parameter, indicates that the variable should be assigned to a machine register, if possible, for greater efficiency. A variable declared register may not have its address taken with the & operator (see section 3.6.2); for a related reason, arrays may not be assigned to registers. The use of the register keyword has greatly diminished in importance as compilers have gotten better at detecting heavily used variables and automatically assigning them to machine registers.
  auto— For a local variable, indicates that the variable should have automatic duration. Because automatic duration is the default for local variables, this storage-class specifier is almost never used. (It is a holdover from C’s predecessor language B.)
  typedef— Indicates that the identifier declared by the declaration is not of an actual variable or function, but rather is to be a synonym for the type that the variable or function would have had. See section 3.2.9.

If a declaration includes an explicit storage-class specifier, the type may be omitted, and defaults to int. Thus,

register r;

is a declaration of an int variable r, which should be placed in a machine register, and

extern a[];

is an external declaration of an array of ints. (The size is omitted because it is set, elsewhere, by the defining declaration of the array.)


Previous Table of Contents Next