Storage class specifiers and storage duration

Storage class specifiers don't specify scope but combine with scope to determine storage duration. Here's the second part in a series on scope, storage allocation, and linkage.

A declaration is a source code construct that 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 might also be a definition, which provides not just some of the attributes of a name, but rather all the information the compiler needs to create the code for that name.

Among the attributes that a name may have are its 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. I've discussed the concept of data types in prior columns.1,2

I devoted my November column to the concept of scope as it applies to C and C++.3 In essence, the scope of a name is that portion of a translation unit in which the name is visible. C and C++ each support several different kinds of scope, summarized in the sidebar entitled "Scope regions in C and C++."

Scope regions in C and C++
C and C++ each support five different kinds of scope regions. Although the C and C++ standards use different names for some regions and different verbiage to define those regions, the two languages support essentially the same five regions:

In C, a name has file scope if it's declared in the outermost scope of a translation unit. C++ extends the concept of file scope to the broader concept of namespace scope. In C++, a name has namespace scope if it's declared either in a namespace definition or in what C calls file scope. The C++ standard refers to the C concept of file scope as global namespace scope, or just global scope.

A name (other than a statement label) has block scope if it's declared within a function definition or a block nested therein.

A name has function prototype scope if it's declared in the function parameter list of a function declaration that is not also a definition.

Each statement label has function scope, which spans the body of the function containing the label.

A name in C++ has class scope if it's declared within the brace-enclosed body of a class definition. Classes in C++ include structures and unions, so a member of a C++ structure or union has class scope as well. The C standard doesn't have a corresponding notion of structure scope, but rather says that each structure or union has a separate name space for its members. Despite the different verbiage in their respective standards, C and C++ look up structure and union members in much the same way.

Scope is closely related to, but nonetheless distinct from, the concepts of storage duration and linkage. The storage duration for an object determines how and when the storage for that object comes and goes. Linkage determines whether declarations in different scopes can refer to the same object or function. It's easy to confuse these concepts because they're so intertwined.

Much of the confusion stems from the complex semantics of storage class specifiers, keywords such as extern and static. For example, the precise meaning of static depends on the scope in which it appears. Sometimes, declaring an object static affects the object's storage duration. It can also affect the object's linkage. Understanding these distinctions can help you program more effectively.

This month, I'll explain the syntax of storage class specifiers and the concept of storage duration in C and C++. I'll also show you how they're related to the concept of scope.