The exact point that a name's scope begins depends on the way that name is declared.
The scope of such a name begins just after the end of its declarator and before its initializer, if present. A "declarator" is the part of an object or function declaration consisting of a name being declared, possibly surrounded by operators such as *, [], and (). For example:
long int *p = NULL, x[N];
has two declarators, *p and x[N]. In this example, p's scope begins at the = (equal sign), and x's scope begins at the semicolon.
The scope of a structure, union, or enumeration tag begins just after the appearance of the tag in the type specifier that first declares the tag. For example, the name s appearing in:
struct s
{
...
};
is a tag. The names of unions and enumerations are also tags. The scope of s in the above declaration begins at the opening brace immediately after s.
Similarly, the general form of an enumeration definition is:
enum tag { enumerator, enumerator, ..., enumerator };
Each enumerator is an identifier that names a constant, optionally followed by an = and an expression that specifies the constant's value. The scope of an enumeration constant begins just after the appearance of its defining enumerator.
Consider:
enum color { red, green = 2, blue = 4 };
Here, red's scope begins at the first comma, green's begins at the second, and blue's begins at the closing brace.
According to the C standard, a name in an inner scope can hide a name from an outer scope. For example, in Listing 1, the object k local to function g hides the global object k. The local k hides the global one in the sense that, when the compiler looks up k in the scope of the local k, it finds only the local k, never the global one. Thus, the assignment in g modifies the local k, not the global one.
The C++ standard explains the behavior of nested scopes differently, but the effect is pretty much the same.
Scope Regions in C++
The scope regions of C++ are somewhat different than those in C. C++ identifies five kinds of scope: function, function prototype, local, namespace, and class. The first two function scope and function prototype scope are the same as in C. Local scope corresponds to C's block scope; namespace scope corresponds to C's file scope; and class scope is something new.
In C++, local scope extends the concept of block scope to account for some added features of C++, such as the ability to declare a variable in the initialization step of a for statement, as in:
for (int i = 0; i < N; ++i)
...
C++ provides a facility called namespaces for grouping names that would otherwise be crowded into file scope. C++ generalizes the rules for names declared at file scope to include names declared in namespaces as well. In C++, a name has namespace scope if it's declared either in a namespace of the form:
namespace identifier
{
...
}
or in what C calls file scope. Accordingly, the C++ standard shuns the term file scope in favor of "global namespace scope", or just "global scope."
C++ also introduces the concept of class scope for names declared within the brace-enclosed body of a class definition. (Classes in C++ include structures and unions, as well.) In C++, each class introduces a new scope, so the same name can be declared as a member in more than one class.
C doesn't quite have a corresponding notion of structure scope. Rather, the C standard says that each structure or union has a separate name space for its members. The C standard uses the term "name space" (two words) to mean something quite different from the namespace (one word) construct of C++. In C, a name space is a region of the compiler's symbol table. Despite the different verbiage in their respective standards, C and C++ look up structure and union members in much the same way.
Scope and Linkage
The concept of scope is meaningful only within a single translation unit. Strictly speaking, a name declared in the global scope is simply a name declared at the outermost scope in a translation unit. That name isn't necessarily known in other translation units.
Despite what you may have learned, neither C nor C++ has any kind of scope that spans from one translation unit to another. Rather, a name declared in one translation unit can refer to a name defined in another translation though a property called external linkage.
Dan Saks is president of Saks & Associates, a C/C++ training and consulting company. For more information about Dan Saks, visit his website at www.dansaks.com. A slightly different version of this article first appeared in 2007 at www.eetimes.com.


