笔记一、全局变量在多个.c文件中共用。
前言
学习C语言有一段时间了,但是一直很懒没有怎么自己编程,工作上的项目也只需要我修改程序,在这里记录一下我自己忘记的一些项目上编程的基础知识,当是自己笔记的云存储吧~
一、问题背景
想要在头文件中定义一个全局变量,包含到两个不同的 .c 文件中,要求全局变量能在两个文件中共用,或者a文件需要使用b文件的某个全局变量。
二、解决方法
1.实例需求
现在项目文件夹有三个文件:a.c、b.c、.c.h,其中a.c和b.c都需要用到同一个变量 uint8_t changeflag 。
2.解决方法(错误的)
刚学习的时候,曾经想过在c.h中声明一个uint8_t changeflag,由于a.c和b.c中都引用了 .h 文件,changeflag 应该就就能共用了。
自己写一个简单的项目时,会发现实际写出来,编译会出错,类似于: Error: L6200E: Symbol changeflag multiply defined (by a.o and b.o). 编译器认为重复定义了changeflag这个变量。查资料发现是因为#include命令只会原封不动的把头文件中的内容搬到#include的位置,相当于a.c和b.c中都执行了一次uint8_t changeflag,导致一个项目中定义了两个变量changeflag,编译器就认为是重复定义了。
2.解决方法(正确的)
使用 extern 关键字来声明变量为外部变量。在其中一个.c文件中定义一个全局变量 changeflag ,然后在另一个要使用 changeflag 这个变量的.c文件中使用 extern 关键字声明一次外部变量。
例如在a.c文件中定义变量changeflag,在b.c文件中声明changeflag 变量为外部变量,这样这两个文件中就能共享这个变量changeflag了。
代码如下(示例):
/*a.c文件中:*/
#include "c.h"
uint8_t changeflag=FALSE;
/*b.c文件中:*/
#include "c.h"
extern uint8_t changeflag;
3.其他解决方法(正确的)
也是使用 extern 关键字来声明变量为外部变量,但是方式略有不同。可以在一个 a.c 文件中定义一个全局变量 changeflag ,然后在引用的 c.h 文件中进行声明,这时b.c 只要引用 c.h 头文件就可以使用 a.c 中定义的全局变量 changeflag 了。
代码如下(示例):
/*a.c文件中:*/
#include "c.h"
uint8_t changeflag=FALSE;
/*c.h文件中:*/
extern uint8_t changeflag;
/*b.c文件中:*/
#include "c.h" //这样就已经可以使用全局变量 changeflag 了。
总结
这个问题就是变量定义和变量声明的区别,变量定义使用“数据类型+变量名称”的形式,编译器会分配内存单元;而变量声明使用“extern 变量类型+变量名称”的形式,向编译器声明这个变量是在其他外部c文件中定义,编译器就不会分配内存空间,直到真正遇到变量定义的时候才会分配内存空间。
在实际使用过程中,以上方法主要适用于编译器能够识别的普通类型变量,记得不要在外部声明时赋初值。
如果需要较多的数据共用时,可以在.h 文件中定义结构体,通过引用 .h 头文件达到同样的目的。
相关注意事项
在《高质量C/C++编程指南》一书中,对此也有说明:
【建议1-2-1】头文件中只存放“声明”,而不存放“定义”。
在C++语法中,类的成员函数可以在声明的同时被定义,并且自动成为内联函数。这虽然会带来书写上的方便,但却造成了风格不一致,弊大于利。建议将成员函数的定义分开,不论该函数体有多么小。
【建议1-2-2】不提倡使用全局变量,尽量不要在头文件中出现现象 extern int value 这类声明。
学习过程中碰到的三个很有用的几个文章:
1.https://www.cnblogs.com/lanhaicode/p/10633125.html
2.https://blog.youkuaiyun.com/qq_41209741/article/details/84108962
3.https://www.cnblogs.com/wangh0802PositiveANDupward/archive/2012/08/06/2624827.html