前言
假设源文件包含某函数的调用,而该函数是定义在另一个文件中,在调用过程中没有声明函数是十分危险的。如果没有函数原型可依赖,编译器会假定函数的返回值是Int类型,并假定形参的数量和函数调用实参的数量相匹配。但是编译器的假定很可能是错误的,但是因为一次只能编译一个文件,所以没办法进行检查。如果这种假定是错误的,那么程序很可能无法工作,而且没有线索可以用来查找原因。因此,就需要在调用函数的文件中声明该函数。
声明和定义
声明是表明变量的类型和名称,变量i可以这样写:
int i;
定义不仅仅是声明,还要对变量分配地址和内存空间,例int i=1; 这样不仅声明i是int类型的变量,而且也对i进行了定义,从而使编译器为i流出了空间。
extern
声明变量i,而不是定义它,需要在声明的开始处安放extern关键字
extern int i;
- extern存储类型使几个源文件可以共享同一个变量。这样的声明给编译器提供的信息是:i是int类型的变量。
- 这样不会导致编译器为变量i分配存储单元。因为上述声明不是变量i的定义,他只是提示编译器需要访问定义在别处的变量(可能稍后在同一文件中,更常见的是在另一个文件中)。
- 变量在程序中可以有多次声明,但只能有一次定义。由于关键字extern的存在,编译器不会在每次编译这些文件时为分配额外的内存空间。
extern用于所有类型的变量。在数组声明中使用extern时,可以省略数组的长度。
extern int a[];
- 为了在几个源文件中共享i,首先把变量i定义放在一个文件中:int i;
- 如果需要对变量i初始化,可以把初始化式放在这里。在编译文件时,编译器会为变量分配内存空间,而其他文件将包含变量i的声明:extern int i;
- 变量\函数定义在其他源文件中,在当前文件使用该变量\函数时前面需加上extern
- 因为局部变量不能作为全局变量任意使用,他只在当前作用域范围内有效,extern可以使得局部变量任意使用。
注意:
- 当同一个变量声明出现在不同文件中时,编译器无法检查声明是否和变量定义相匹配。例如,一个文件的声明可以包含定义:int i; 同时另一个文件包含声明extern long i; 这类错误可能导致程序行为异常。
- 为了避免不一致,通常把共享变量的声明放在头文件中。需要访问特定变量的源文件可以包含相应头文件。此外,含有变量定义的源文件需要包含含有相应变量声明的头文件,这样编译器就可以检查声明和定义是否匹配。