您需要区分两个独立的概念:函数定义和符号声明。"extern"是一个链接修饰符,它是对编译器的一个提示,说明后面引用的符号定义在哪里(提示是,"不在这里")。
如果我写
extern int i;
在C文件的文件范围内(函数块之外),那么你说“变量可能在其他地方定义”。
extern int f() {return 0;}
既是函数f的声明,也是函数f的定义。在这种情况下,定义覆盖了extern。
extern int f();
int f() {return 0;}
首先是声明,然后是定义。
如果您想声明和同时定义一个文件作用域变量,使用extern是错误的。例如,
extern int i = 4;
将给出一个错误或警告,这取决于编译器。
如果显式地希望避免定义变量,则使用extern非常有用。
让我解释一下:
假设文件a.c包含:
#include "a.h"
int i = 2;
int f() { i++; return i;}
文件a.h包括:
extern int i;
int f(void);
文件b.c包含:
#include <stdio.h>
#include "a.h"
int main(void){
printf("%d\n", f());
return 0;
}
The extern in the header is useful, because it tells the compiler during the link phase, "this is a declaration, and not a definition". If I remove the line in a.c which defines i, allocates space for it and assigns a value to it, the program should fail to compile with an undefined reference. This tells the developer that he has referred to a variable, but hasn't yet defined it. If on the other hand, I omit the "extern" keyword, and remove the int i = 2 line, the program still compiles - i will be defined with a default value of 0.
文件作用域变量是隐式定义的,如果没有显式地为它们赋值,则默认值为0或NULL——这与在函数顶部声明的块作用域变量不同。extern关键字避免了这种隐式定义,因此有助于避免错误。
对于函数,在函数声明中,关键字确实是多余的。函数声明没有隐式定义。