用 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"
- externunsigned char key;
其实就是变量定义和变量声明的区别, 变量定义使用 "数据类型 + 变量名称" 的形式, 编译器需要给他分配内存单元的; 而变量声明使用 "extern 变量类型 + 变量名称" 的形式, 是告诉编译器我这个变量将在其他外部 c 文件中定义, 我这里只是在外部用它. 编译器就不给他分配内存空间, 而等到真正遇到变量定义的时候再给他分配内存空间.
1, 普通变量定义成全局变量
如果是普通类型, 完全可以不用 *.h 文件, 直接在 *.c 文件中定义, 在调用文件处用 extern 声明, 因为对于普通类型, 编译器是可以识别的. 比如在一个 my.c 文件中, 我定义了 char name[10]; 那么在别的文件中只要用 extern char name[](由于是声明, 一位数组可以省略大小, 但不建议用指针, 比较指针和数组是两回事)外部声明就可以了, 告诉编译器这个变量我已经定义过了, 具体怎样, 你慢慢找吧. 这符合常理, 因为 char 是编译器能自主识别的类型.
2, 自定义结构体类型定义成全局变量 不同于普通类型, 如果不预先通知编译器, 编译器是不会识别你自定义的类型的. 这个时候,*.h 文件便出现了. 不是定义结构类型不占内存吗? 那好, 我大结构体的定义放在 *.h 文件中, 这样一来, 无论你 incude 无数次, 内存都不会被占用的. 而且这样还有个好处, 在别的文件中可以 include 这个 *.h 文件, 这样, 在这个文件中, 编译器就可以识别你的自定义类型了, 目的不就达到了? 假如我在 global.h 中定义了
- typedef struct _POSITION
- {
- int x;
- int y;
- }POSITION;
那么我可以在一个 global.c 文件中实现全局变量的定义, 不过要 include 那个 *.h 文件, 比如 /* ***global.c ******* */
- include "global.h"
- POSITION current,;
这样就定义了 cunrrent 这个变量, 在别的文件中引用这个变量时, 只要 extern POSITION current; 进行声明, 然后就可以用了, 不过这个文件也还得 include "global.h" 因为如果不包含, 在这个文件中是不识别 POSITION 类型的.
1. 如何引用一个已经定义过的全局变量?
答: extern 可以用引用头文件的方式, 也可以用 extern 关键字, 如果用引用头文件方式来引用某个在头文件中声明的全局变理, 假定你将那个编写错了, 那么在编译期间会报错, 如果你用 extern 方式引用时, 假定你犯了同样的错误, 那么在编译期间不会报错, 而在连接期间报错.
2. 全局变量可不可以定义在可被多个. C 文件中? 为什么?
答: 可以, 在不同的 C 文件中以 static 形式来声明同名全局变量.
可以在不同的 C 文件中声明同名的全局变量, 前提是其中只能有一个 C 文件中对此变量赋初值, 此时连接不会出错.
来源: http://www.bubuko.com/infodetail-3202868.html