Storage-Class Specifiers for External-Level Declarations

External variables are variables at file scope. They are defined outside any function, and they are potentially available to many functions. Functions can only be defined at the external level and, therefore, cannot be nested. By default, all references to external variables and functions of the same name are references to the same object, which means they have “external linkage.” (You can use the static keyword to override this. See information later in this section for more details on static.)

Variable declarations at the external level are either definitions of variables (“defining declarations”), or references to variables defined elsewhere (“referencing declarations”).

An external variable declaration that also initializes the variable (implicitly or explicitly) is a defining declaration of the variable. A definition at the external level can take several forms:

In variable declarations at the external level (that is, outside all functions), you can use the static or extern storage-class specifier or omit the storage-class specifier entirely. You cannot use the auto and register storage-class-specifier terminals at the external level.

Once a variable is defined at the external level, it is visible throughout the rest of the translation unit. The variable is not visible prior to its declaration in the same source file. Also, it is not visible in other source files of the program, unless a referencing declaration makes it visible, as described below.

The rules relating to static include:

The rules for using extern are:

Example

The example below illustrates external declarations:

/******************************************************************
                      SOURCE FILE ONE 
*******************************************************************/

extern int i;                /* Reference to i, defined below */
void next( void );           /* Function prototype            */

void main()
{
    i++;
    printf( "%d\n", i );     /* i equals 4 */
    next();
}

int i = 3;                   /* Definition of i */

void next( void )
{
    i++;
    printf( "%d\n", i );     /* i equals 5 */
    other();
}

/******************************************************************
                      SOURCE FILE TWO 
*******************************************************************/

extern int i;                /* Reference to i in  */
                             /* first source file  */
void other( void )
{
    i++;
    printf( "%d\n", i );     /* i equals 6 */
}

The two source files in this example contain a total of three external declarations of i. Only one declaration is a “defining declaration.” That declaration,

int i = 3;

defines the global variable i and initializes it with initial value 3. The “referencing” declaration of i at the top of the first source file using extern makes the global variable visible prior to its defining declaration in the file. The referencing declaration of i in the second source file also makes the variable visible in that source file. If a defining instance for a variable is not provided in the translation unit, the compiler assumes there is an

extern int x;

referencing declaration and that a defining reference

int x = 0;

appears in another translation unit of the program.

All three functions, main, next, and other, perform the same task: they increase i and print it. The values 4, 5, and 6 are printed.

If the variable i had not been initialized, it would have been set to 0 automatically. In this case, the values 1, 2, and 3 would have been printed. See Initialization for information about variable initialization.