外部级别声明的存储类说明符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." (可以使用 static 关键字进行替代。(You can use the static keyword to override this. 有关 static 的更多详细信息,请参阅本节后面的信息。)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:

  • 使用 static 存储类说明符声明的变量。A variable that you declare with the static storage-class specifier. 可以使用常量表达式显式初始化 static 变量,如初始化中所述。You can explicitly initialize the static variable with a constant expression, as described in Initialization. 如果省略初始值设定项,默认情况下变量将初始化为 0。If you omit the initializer, the variable is initialized to 0 by default. 例如,这两个语句都被视为变量 k 的定义。For example, these two statements are both considered definitions of the variable k.

    static int k = 16;  
    static int k;  
    
  • 在外部级别显式初始化的变量。A variable that you explicitly initialize at the external level. 例如,int j = 3; 是变量 j 的定义。For example, int j = 3; is a definition of the variable j.

    在外部级别的变量声明中(即,这些函数的外部),可以使用 static 或 extern 存储类说明符或完全忽略存储类说明符。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. 无法在外部级别使用 auto 和 register storage-class-specifier 终止符。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.

    与 static 相关的规则包括:The rules relating to static include:

  • 所有块的外部声明的不带有 static 关键字的变量在整个程序中始终保留其值。Variables declared outside all blocks without the static keyword always retain their values throughout the program. 若要限制其特定翻译单元的访问,则必须使用 static 关键字。To restrict their access to a particular translation unit, you must use the static keyword. 这将为它们提供“内部链接”。This gives them "internal linkage." 若要使其成为整个程序的全局变量,请忽略显式存储类或使用关键字 extern(请参阅下一个列表中的规则)。To make them global to an entire program, omit the explicit storage class or use the keyword extern (see the rules in the next list). 这将为它们提供“外部链接”。This gives them "external linkage." 内部链接和外部链接也在链接中进行了讨论。Internal and external linkage are also discussed in Linkage.

  • 在程序中,只可在外部级别定义变量一次。You can define a variable at the external level only once within a program. 可以在不同的翻译单元中定义具有相同名称和 static 存储类说明符的另一个变量。You can define another variable with the same name and the static storage-class specifier in a different translation unit. 由于每个 static 定义只在其自己的翻译单元中可见,因此不会发生任何冲突。Since each static definition is visible only within its own translation unit, no conflict occurs. 这样一来,可以隐藏必须在单个翻译单元的函数之间共享但对其他翻译单元不可见的标识符名称。This provides a useful way to hide identifier names that must be shared among functions of a single translation unit, but not visible to other translation units.

  • static 存储类说明符也可应用于函数。The static storage-class specifier can apply to functions as well. 如果声明函数 static,则其名称在用于声明它的文件的外部不可见。If you declare a function static, its name is invisible outside of the file in which it is declared.

    有关使用 extern 的规则为:The rules for using extern are:

  • extern 存储类说明符声明对在其他位置定义的变量的引用。The extern storage-class specifier declares a reference to a variable defined elsewhere. 可以使用 extern 声明使另一个源文件中的定义可见,或使变量在同一源文件中的定义之前可见。You can use an extern declaration to make a definition in another source file visible, or to make a variable visible prior to its definition in the same source file. 一旦在外部级别声明对变量的引用,则该变量翻译单元的其余部分是可见的,直到声明的引用出现。Once you have declared a reference to the variable at the external level, the variable is visible throughout the remainder of the translation unit in which the declared reference occurs.

  • 若要使 extern 引用有效,必须定义其引用的变量一次,并且仅在外部级别定义一次。For an extern reference to be valid, the variable it refers to must be defined once, and only once, at the external level. 此定义(没有 extern 存储类)可位于构成程序的任何翻译单元中。This definition (without the extern storage class) can be in any of the translation units that make up the program.

示例Example

下面的示例阐释了外部声明:The example below illustrates external declarations:

/******************************************************************  
                      SOURCE FILE ONE   
*******************************************************************/  
#include <stdio.h>  

extern int i;                // Reference to i, defined below   
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 的总共三个外部声明。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;  

定义全局变量 i 并使用初始值 3 对其进行初始化。defines the global variable i and initializes it with initial value 3. 位于使用 i 的第一个源文件顶部的 extern 的“引用”声明使全局变量在其文件中的定义声明之前可见。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. 此外,第二个源文件中的 i 的引用声明使变量在该源文件中可见。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.

所有三个函数(mainnextother)都执行同一任务:它们增大 i 并将其打印。All three functions, main, next, and other, perform the same task: they increase i and print it. 打印值 4、5 和 6。The values 4, 5, and 6 are printed.

如果尚未初始化变量 i,则会自动将其设置为 0。If the variable i had not been initialized, it would have been set to 0 automatically. 在这种情况下,值 1、2 和 3 可能已打印。In this case, the values 1, 2, and 3 would have been printed. 有关变量初始化的信息,请参阅初始化See Initialization for information about variable initialization.

另请参阅See Also

C 存储类C Storage Classes