C extern 关键词分析
C extern 关键词分析
作用
首先我们区分两个 术语
- 声明 (declaration) : 仅表示,存在 变量 / 函数,变量的类型 / 函数的参数和返回值,并不分配内存 / 定义实现
- 定义 (definition) : 除了 声明 的作用外,还为变量分配内存 / 定义函数实现。
- 声明 是 定义 的功能子集
- 声明 可以多次,但 定义 只能一次
所以其作用可以解释为
- 增加变量 / 函数的可见范围,即,可以使用程序内任一位置定义的变量 / 函数
- 带有 extern 声明时,编译器认为在程序的某一位置有所定义,因此不会报错,而会使用该声明继续编译
函数
函数的声明 / 定义 默认带有 extern 关键字
int foo(int arg1, char arg2);
被编译器视为
extern int foo(int arg1, char arg2);
编译器认为在程序的某一位置,该函数有所定义,因此不会报错,而会使用该声明继续编译
变量
变量的声明 默认不带有 extern 关键字
-
区分 声明 和 定义
// 仅声明 extern int var; // 定义 int var; // 声明必须显式地带上extern关键字,否则会混淆定义和声明,声明时不分配内存
-
代码分析
-
编译通过,var在全局定义
int var; int main(void) { var = 10; return 0; }
-
编译通过,var在全局声明,虽然没有其他位置定义,但并未使用
extern int var; int main(void) { return 0; }
-
编译不通过,var在全局声明,而且试图修改值,但并未定义,故在链接时会报错
extern int var; int main(void) { var = 10; return 0; }
-
如果在其他文件定义var,则上述情况没有问题
#include "somefile.h" // #pragma once // int var; extern int var; int main(void) { var = 10; return 0; }
-
声明时定义,视为定义
以下代码,视为全局定义var (分配内存),因此编译通过
extern int var = 0;
int main(void) {
var = 10;
return 0;
}
总结
- 声明可以多次,定义只有一次
- extern 声明可以视为,在程序的某一处有定义,并且可以使用,顺利编译;如果没有定义,可能出现链接错误
- 函数声明默认 extern,变量声明需要显式extern
- 变量 extern 声明,并初始化时,视为定义