1. 定义只能进行一次,声明可以多次。
2. 变量定义是为变量分配存储空间,也可以初始化,不初始化的定义如:int i;
3. 声明是表明变量的类型和名称,因此定义也是声明。
4 . 没有初始化的时候,有extern表示这是声明,不是定义,不分配存储空间,如:extern int i;
5. 但是如果有初始化时,即使加了extern也是定义,如:extern int i = 0,这个时候i只能在函数外部定义。
6. 没有extern的声明都可以看做是定义,如第二条。
具有文件作用域的变量或函数,其链接属性默认是extern的,使用static可将(而且是仅仅这种情况下才能改变)缺省链接属性为extern声明的链接属性改为源文件私有的链接属性,即internal。
在函数内部,如果在变量声明中加入extern,则指定改变量的链接属性为external,这样该函数就可以访问在其他源文件声明的外部变量了。
正常来说,只有在声明的时候,加上static或extern才是必须的,但为了人为理解方便,建议是在一个地方定义变量以后(最好别把定义放在头文件里),并在使用这个变量的其他源文件处的声明中加上extern关键字,增加易读性。
extern关键字用于源文件中一个标识符的第一次声明时,它指定该标识符具有external链接属性,但是如果它用于该标识符第二次或以后的声明时,它并不会改变第一次声明所指定的链接属性,如:
static int i;
int func()
{
int j;
extern int k;
extern int i;
……
}
函数内部的i并不改变链接属性为internal的i的链接属性。
举例说明
对于extern关键字来说,比较常用的场景是:
a.c需要引用b.c中定义的全局变量(注意是全局变量,假设为i),需要在a.c中,先声明:extern int i;然后就可以直接使用i了。而i的定义则在b.c中,且不需要加extern关键字,因为默认的链接属性已经是extern了,更确切地说,只在声明中使用extern即可(结合第四条理解)。
另外一种选择,可以在a.h中以extern来声明b.c中的那个变量i。这两种方法都可以,但是在大型软件中,还是第一种方法效率更高(加速程序编译过程的预处理的速度)。
相关内容见《C和指针》41页