外部变量是文件范围内的变量。 它们在任何函数的外部定义,并且可能对许多函数可用。 只能在外部级别定义函数,因此不能将其嵌套。 默认情况下,所有对同名外部变量和函数的引用都是对同一个对象的引用,也就是说它们具有外部链接。 (可以使用 static 关键字来替代此行为。)
外部级别的变量声明要么是变量的定义(定义声明),要么是对其他地方定义的变量的引用(引用声明)。
(隐式或显式)初始化变量的外部变量声明是变量的定义声明。 外部级别的定义可采用多种形式:
- 使用 - static存储类说明符声明的变量。 可以使用常数表达式来显式初始化- static变量,如初始化中所述。 如果省略初始值设定项,默认情况下变量将初始化为 0。 例如,这两个语句都被视为变量- k的定义。- static int k = 16; static int k;
- 在外部级别显式初始化的变量。 例如, - int j = 3;是变量- j的定义。
在外部级别(即在所有函数之外)的变量声明中,可以使用 static 或 extern 存储类说明符,也可以完全省略存储类说明符。 不能在外部级别使用 auto 和 registerstorage-class-specifier 终止符。
一旦在外部级别定义变量,该变量在翻译单元的其余部分便可见。 该变量在同一源文件中的声明之前不可见。 此外,除非引用声明使其可见,否则它在程序的其他源文件中不可见,如下文所述。
与 static 相关的规则包括:
- 在所有块之外声明的、没有 - static关键字的变量在整个程序中始终保持自己的值不变。 若要限制它们对特定翻译单元的访问,必须使用- static关键字。 这给了它们内部链接。 若要使其成为整个程序的全局变量,请忽略显式存储类或使用关键字- extern(请参阅下一个列表中的规则)。 这给了它们外部链接。 内部链接和外部链接也在链接中进行了讨论。
- 在程序中,只可在外部级别定义变量一次。 可以在不同的翻译单元中定义另一个具有相同名称和 - static存储类说明符的变量。 由于每个- static定义只在它自己的翻译单元中可见,因此不会发生任何冲突。 这提供了一种实用的方法来隐藏标识符名称,这些标识符名称必须在一个翻译单元的函数之间共用,但对其他翻译单元不可见。
- static存储类说明符也可以应用于函数。 如果你声明函数- static,那么它的名称在声明它的文件之外是不可见的。
有关使用 extern 的规则为:
- extern存储类说明符声明对在其他位置定义的变量的引用。 可以使用- extern声明让另一个源文件中的定义可见,或让变量先于同一源文件中的定义可见。 一旦你在外部级别声明了对变量的引用,此变量就在声明的引用所在的整个翻译单元的其余部分都是可见的。
- 若要使 - extern引用有效,必须定义其引用的变量一次,并且仅在外部级别定义一次。 此定义(没有- extern存储类)可位于构成程序的任何翻译单元中。
示例
下面的示例阐释了外部声明:
/******************************************************************
                      SOURCE FILE ONE
*******************************************************************/
#include <stdio.h>
extern int i;                // Reference to i, defined below
extern void other ( void );  // Reference to other(), defined in second source file
void next( void );           // Function prototype
int main()
{
    i++;
    printf_s( "%d\n", i );   // i equals 4
    next();
}
int i = 3;                  // Definition of i
void next( void )
{
    i++;
    printf_s( "%d\n", i );  // i equals 5
    other();
}
/******************************************************************
                      SOURCE FILE TWO
*******************************************************************/
#include <stdio.h>
extern int i;              // Reference to i in
                           // first source file
void other( void )
{
    i++;
    printf_s( "%d\n", i ); // i equals 6
}
此示例中的两个源文件包含 i 的总共三个外部声明。 仅一个声明是“定义声明”。该声明
int i = 3;
定义全局变量 i 并使用初始值 3 对其进行初始化。 使用 i 的第一个源文件顶部的 extern 的“引用”声明让全局变量先于文件中的定义声明可见。 此外,第二个源文件中的 i 的引用声明使变量在该源文件中可见。 如果翻译单元中未提供变量的定义实例,则编译器假定有
extern int x;
一个引用声明,并且定义引用
int x = 0;
出现在程序的另一个翻译单元中。
所有三个函数(main、next 和 other)都执行同一任务:它们增大 i 并将其打印。 打印值 4、5 和 6。
如果变量 i 还没有被初始化,则会自动设置为 0。 在这种情况下,值 1、2 和 3 可能已打印。 有关变量初始化的信息,请参阅初始化。