The scope of an identifier is the range of the program in which the declared identifier has meaning. An identifier has meaning if it is recognized by the compiler. Scope is determined by the location of the identifier's declaration. Trying to access an identifier outside of its scope results in an error. Every declaration has one of four kinds of scope:
An enumeration constant's scope begins at the defining enumerator in an enumerator list. The scope of a statement label includes the entire function body. The scope of any other type of identifier begins at the identifier itself in the identifier's declaration. See the following sections for information on when an identifier's scope ends.
An identifier whose declaration is located outside any block or
function parameter list has file scope. An identifier
with file scope is visible from the declaration of the identifier
to the end of the compilation unit, unless hidden by an inner
block declaration. In the following example, the identifier
off
has file scope:
int off = 5; /* Declares (and defines) the integer identifier off. */ main () { int on; /* Declares the integer identifier on. */ on = off + 1; /* Uses off, declared outside the function block of main. This point of the program is still within the active scope of off. */ if (on<=100) { int off = 0;/* This declaration of off creates a new object that hides the former object of the same name. The scope of the new off lasts through the end of the if block. */ off = off + on; return off; } }
An identifier appearing within a block or in a parameter list of a function definition has block scope and is visible within the block, unless hidden by an inner block declaration.
Block scope begins at the identifier declaration and ends at
the closing brace (}) completing the block. In the following
example, the identifier red
has block scope and
blue
has file scope:
int blue = 5; /* blue: file scope */ main () { int x = 0 , y = 0; /* x and y: block scope */ int red = 10; /* red: block scope */ x = red + blue; }
Only statement labels have function scope (see Chapter 7). An identifier with function scope
is unique throughout the function in which it is declared. Labeled
statements are used as targets for goto
statements and
are implicitly declared by their syntax, which is the label followed
by a colon (:) and a statement. For example:
int func1(int x, int y, int z) { label: x += (y + z); /* label has function scope */ if (x > 1) goto label; } int func2(int a, int b, int c) { if (a > 1) goto label; /* illegal jump to undefined label */ }
See Section 7.1 for more information on statement labels.
An identifier that appears within a function prototype's list of parameter declarations has function prototype scope. The scope of such an identifier begins at the identifier's declaration and terminates at the end of the function prototype declaration list. For example:
int students ( int david, int susan, int mary, int john );
In this example, the identifiers (david, susan, mary
,
and john
) have scope beginning at their declarations
and ending at the closing parenthesis. The type of the function
students
is "function returning int
with
four int
parameters." In effect, these identifiers are
merely placeholders for the actual parameter names to be used after
the function is defined.