🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 例子 在下面的例子中,我们创建了两个源文件 main.c 和 module.c: * module.c 是整个程序的一个模块,我们在其中定义了一个全局变量和一个函数; * main.c 是程序的主模块(主文件),它使用到了 module.c 中的变量和函数。 module.c 源码: ~~~ #include <stdio.h> int m = 100; void func() { printf(" module c \n"); } ~~~ main.c 源码: ~~~ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> extern void func(); extern int m; int n = 200; int main() { func(); printf("m = %d, n = %d\n", m, n); getchar(); return 0; } ~~~ 在 Visual Studio 中,将两个源文件都添加到工程中,点击“运行(Run)”按钮就可以运行程序。 在 Linux GCC 中,可以使用下面的命令来编译和运行程序: ~~~ $gcc main.c module.c $./a.out ~~~ 程序最终的运行结果为: ~~~ Multiple file programming! m = 100, n = 200 ~~~ m 和 n 是在所有函数之外定义的全局变量(Global Variable),它的作用域默认是整个程序,也就是所有的代码文件,包括`.c`和`.h`文件。 > 如果你一直在编写单个源文件的程序,那么请注意,全局变量的作用范围不是从变量定义处到该文件结束,在其他文件中也有效。 这里需要重点理解的是extern关键字,它用来声明一个变量或函数 # extern关键字 我们知道,C语言代码是由上到下依次执行的,不管是变量还是函数,原则上都要先定义再使用,否则就会报错。但在实际开发中,经常会在函数或变量定义之前就使用它们,这个时候就需要提前声明。 所谓声明(Declaration),就是告诉编译器我要使用这个变量或函数,你现在没有找到它的定义不要紧,请不要报错,稍后我会把定义补上。 例如,我们知道使用 printf()、puts()、scanf()、getchar() 等函数要引入 stdio.h 这个头文件,很多初学者认为 stdio.h 中包含了函数定义(也就是函数体),只要有了头文件程序就能运行。其实不然,头文件中包含的都是函数声明,而不是函数定义,函数定义都在系统库中,只有头文件没有系统库在链接时就会报错,程序根本不能运行。 变量和函数不同,编译器只能根据 extern 来区分,有 extern 才是声明,没有 extern 就是定义。 变量的定义有两种形式,你可以在定义的同时初始化,也可以不初始化: ~~~ datatype name = value; datatype name;  ~~~ 而变量的声明只有一种形式,就是使用 extern 关键字: ~~~ extern datatype name; ~~~ 另外,变量也可以在声明的同时初始化,格式为: ~~~ extern datatype name = value; ~~~ 这种似是而非的方式是不被推荐的,有的编译器也会给出警告,我们不再深入讨论,也建议各位读者把定义和声明分开,尽量不要这样写。 extern 是“外部”的意思,很多教材讲到,extern 用来声明一个外部(其他文件中)的变量或函数,也就是说,变量或函数的定义在其他文件中。 不过我认为这样讲不妥,因为除了定义在外部,定义在当前文件中也是正确的。例如,将 module.c 中的`int m = 100;`移动到 main.c 中的任意位置都是可以的。所以我认为,extern 是用来声明的,不管具体的定义是在当前文件内部还是外部,都是正确的。