用C 语言编写程序的时候,我们经常会遇到这样一种情况: 希望在头文件中定义一个全局变量,然后包含到两个不同的c 文件中,希望这个全局变量能在两个文件中共用 。
举例说明:项目文件夹project 下有 main.c 、 common.c 和 common.h 三个文件,其中 common.h 文件分别 #include 在 main.c 和 common.c 文件中。现在希望声明一个字符型变量 key ,在 main.c 和 common.c 中公用。 如下图所示:
有人想,既然是想两个文件都用,那就在common.h 中声明一个 unsigned char key ,然后由于包含关系,在 main.c 和 common.c 中都是可见的,所以就能共用了。
这种想法其实是很多初学者都会想到的,想起来确实有道理,但是实际写出来,我们发现编译的时候编译器提示出错,一般提示大概都类似于:Error: L6200E: Symbol key multiply defined (by common.o and main.o). 也就是说编译器认为我们重复定义了key 这个变量。这是因为 #include 命令就是原封不同的把头文件中的内容搬到 #include 的位置,所以相当于 main.c 和 common.c 中都执行了一次 unsigned char key ,而 C语言中全局变量是项目内(或者叫工程内)可见的 ,这样就造成了一个项目中两个变量key ,编译器就认为是重复定义。
正确的解决办法:使用extern关键字来声明变量为外部变量。具体说就是在其中一个c 文件中 定义一个全局变量key,然后在另一个要使用key这个变量的c 文件中使用 extern关键字声明一次,说明这个变量为外部变量,是在其他的c 文件中定义的全局变量。请注意我这里的用词: 定义和声明。例如在main.c 文件中定义变量 key ,在 common.c 文件中声明 key 变量为外部变量,这样这两个文件中就能共享这个变量 key了,如下图所示。
代码如下(只写跟我们所说问题有关的部分):
(1 ) main.c 文件
#include "common.h" unsigned char key;
(2 ) common.c 文件:
#include "common.h" extern unsigned char key;
很多人看了可能糊涂,这里稍微说一下,其实就是变量定义和变量声明的区别,变量定义使用“ 数据类型 + 变量名称 ” 的形式 ,编译器需要给他分配内存单元的;而变量声明使用“ extern 变量类型 + 变量名称 ” 的形式,是告诉编译器我这个变量将在其他外部 c 文件中定义,我这里只是在外部用它 。编译器就不给他分配内存空间,而等到真正遇到变量定义的时候再给他分配内存空间。
由于很多人从开始学C 语言就一直把 定义变量叫声明变量,一开始就叫错了,所以导致现在分不清定义和声明的区别。要是还理解不了就想想函数的定义和声明,函数定义是编写函数功能实体,编译器要编译这个函数并且要分配内存空间,而函数声明并不生成函数功能实体,只是告诉编译器这是个函数,这个函数在后面将会定义实体,我这里只是提前用,编译器就会接着继续往下编译,如果子函数写在main 函数之后,那么声明是必须的,如果不声明函数编译器都不知道这是个函数,编译就会报错。
说了这么多应该说明白了,如果还有问题可以参考谭浩强的那本C 语言书,书中有详细解释和例子。