C支持4种存储类型说明符:
extern static register auto
这些说明符告诉编译程序应该怎样保存有关变量。存储类型说明符放在其修饰的变量生明之前,其一般形式是:
① storage_specifiertype var_name;
*注* C89和C99均规定,typedef从造句方便上讲是存储类型说明符,而从通常的术语上讲不是存储类型说明符。
在介绍extern之前,先对C链接作一简要说明。② C定义了三类链接:外部链接,内部链接和无链接。
③函数和全局变量具有外部链接。这意味着它们对构成程序的所有文件都是可用的。
④声明为static的文件域对象具有内部链接,仅在声明它们的文件中是已知的。
⑤局部变量没有链接,仅在它们自己的块中是已知的。
⑥extern的主要用途是说明在程序的其它地方用外部链接声明的对象。
为了说明其重要性,有必要了解一下⑦声明和定义之间的区别:声明表述对象的名称和类型,定义则导致为对象分配存储空间。同一个对象可以有许多声明,但只能有一个定义。在很多情况下变量的声明也是定义。但是,通过在变量名之前加上extern说明符,
可以声明变量而不必定义它。这样,当需要引用在程序的其它地方定义的变量时,则只
需要用extern声明该变量。
下面是使用extern的一个实例。注意全局变量first和last是在main之后定义的。
#include<stdio.h>
int main(void)
{
Extern int first,last;/*use global vars*/
printf(“%d %d”,first,last);
return 0;
}
/*global definitonof first and last*/
该程序的输出为 10 20 ,因为printf语句使用的全局变量first和last被初始化为这两个值。由extern声明告诉编译程序,first和last是在其它地方声明的(此处是在同一文件
的稍后),所以,即使first和last在它们的定义之前使用。也能无错地对该程序进行编译。
前面的程序所示的extern变量声明之所以是必要的,仅仅因为在main中使用first和last
之前尚无定义它们。(关于为什么编译器要求变量在使用之前必须先定义,请看编译原理)。倘若在main之前定义了这两个变量,则无需extern语句。
⑧ 切记,如果编译程序发现了没有在当前块中声明的变量,则检验该变量是否与外部
块中的任何变量匹配(如果有很多嵌套的外部块,则从内向外层层匹配,直到最外层的外部块)。若果不匹配,编译程序便检查全局变量;如果找到了匹配的变量,编译程序
便假定它就是所要引用的变量。当需要使用文件中稍后定义的变量时,需要extern说明符。
如上所述,extern允许不加定义地声明变量。但是,如果同时将变量初始化,那么extern
声明将变成定义。明白这一点很重要。
⑨ extern的重要用途与多文件程序有关。C允许程序分散在两个或多个文件之中。分别编译,然后再链接到一起。在这种情况下,必须以某种方式,将程序所需要的全局变量通知给所有不在其定义的文件之外的其它文件。最佳方式(也是最便捷的方式)就是:
在一个文件中定义所有的全局变量,而在另一个文件中使用extern声明前面定义的所有的变量,
文件1 文件2 文件3
int x,y; externint x,y; #include<文件2>
char ch; externchar ch; int main(void)
{
…
x=5;
y= 10;
ch=’A’;
…
}
在文件3中,存储类型说明符extern通知编译程序,告知其后变量的类型和名字已在程序的别的文件中定义。换言之,extern使编译程序了解这些全局变量的类型和名字,同时又不再为之分配内存。当链接程序链接各模块时,自动理解文件中对外部变量的引用。
最后说明一点⑩:在实际开发中,多文件程序和extern声明通常包含在头部中,头部直接由每个源代码文件包含。如上程序所示。
extern也可用于函数声明,但这样做是多余的。不过为了一目了然,实际开发中还是象变量一样用extern声明函数。