Previous: 14.1.3 External Variables
Up: 14.1 Storage Classes
Next: 14.1.5 An Example: Lexical Scanner
Previous Page: 14.1.3 External Variables
Next Page: 14.1.5 An Example: Lexical Scanner
Up until now, we have been using the term declaration rather loosely when referring to variables. In this section, we will ``tighten'' the definition of this term. So far when we have ``declared'' a variable, we have meant that we have told the compiler about the variable; i.e. its type and its name, as well as allocated a memory cell for the variable (either locally or globally). This latter action of the compiler, allocation of storage, is more properly called the definition of the variable. The stricter definition of declaration is simply to describe information ``about'' the variable.
So far, we have used declarations to declare variable names and types as well as to define memory for them. Most of the time these two actions occur at the same time, that is, most declarations are definitions; however, this may not always be the case.
We have already seen an analogous case illustrating the difference between declaring and defining with functions. The prototype statement for a function declares it, i.e. tells the compiler ``about'' the function - its name, return type, and number and type of its parameters. A similar statement, the function header, followed by the body of the function, defines the function - giving the details of the steps to perform the function operation.
For automatic and register variables, there is no difference between definition and declaration. The process of declaring an automatic or a register variable defines the variable name and allocates appropriate memory. However, for external variables, these two operations may occur independently. This is important because memory for a variable must be allocated only once, to ensure that access to the variable always refers to the same cell. Thus, all variables must be defined once and only once. If an external variable is to be used in a file other than the one in which it is defined, a mechanism is needed to ``connect'' such a use with the uniquely defined external variable cell allocated for it. This process of connecting the references of the same external variable in different files, is called resolving the references.
As we saw in the previous section, external variables may be defined and declared with a declaration statement outside any function, with no storage class specifier. Such a declaration allocates memory for the variable. A declaration statement may also be used to simply declare a variable name with the extern storage class specifier at the beginning of the declaration. Such a declaration specifies that the variable is defined elsewhere, i.e. memory for this variable is allocated in another file. Thus, access to an external variable in a file other than the one in which it is defined is possible if it is declared with the keyword extern; no new memory is allocated. Such a declaration tells the compiler that the variable is defined elsewhere, and the code is compiled with the external variable left unresolved. The reference to the external variable is resolved during the linking process.
Here are some examples of declarations of external variables that are not definitions:
extern char stack; extern int stkptr;
These declarations tell the compiler that the variables stack and stkptr are defined elsewhere, usually in some other file. If the keyword extern were omitted, the variables would be considered to be new ones and memory would be allocated for them. Remember, access to the same external variable defined in another file is possible only if the keyword extern is used in the declaration. Figure 14.4 shows an example of a source program that references the same external variable in different files.
The files are assumed to be compiled separately and linked together to create a load module. A sample run is shown below.