本帖最后由 dffzh 于 2025-4-29 09:10 编辑
#申请原创#
@21小跑堂
从事软件开发的你是否见过全局变量满天飞的代码?
是否见过全局搜索全局变量后会弹出来N个调用的情况?然后来一句“Oh, My god”…
反正我见过,长得类似下面这些代码(紫色的变量为全局变量):
简单解释一下全局变量:又叫外部变量,其作用域为整个文件或整个代码工程。 从它的解释就可以看出,全局变量使用起来确实方便;但是,在代码量多且比较复杂的程序里,如果过度使用全局变量,则会导致不仅限于以下的常见问题: 代码耦合度高:很多源文件里都有对全局变量的读写操作,代码相互耦合; 调试难度大:遇到Bug时,由于读写全局变量的代码段太多,排查难度变大; 可维护性差:软件版本迭代或者移交给其他同事,可能人家需要花费大量精力去理解; 健壮性差:全局变量在整个工程被读写操作,特别是出现在临界代码区或者中断函数里面时,代码稳定性显著降低,容易出现意想不到的偶发性Bug。 可能还有其他问题,特别是在基于操作系统的软件开发应用中,因此,作者强烈建议尽量少用或者尽量不直接暴露全局变量。 那问题又来了,我不用全局变量,那用啥?到底有哪些方法可以减少全局变量的使用频次呢?这篇文章作者将通过一些实战经验代码与大家分享一下如何减少全局变量的使用。
1、使用静态变量替换全局变量 不推荐使用全局变量实现的计数器功能代码: int counter = 0; counter++; 推荐使用用函数封装+静态变量实现: int count(void) { static int counter = 0; counter++; return counter; }
2、使用结构体封装数据 不推荐直接使用全局变量定义长方形的长,宽和面积: float length =0; float width = 0; float area = 0; 推荐使用结构体来封装数据,便于管理: typedef struct { float length; float width; float area; }st_rectangle;
3、使用函数参数传递数据
不推荐如下方式传递数据: int value; void set_para(void) { value = 66; } 推荐使用如下方式: void set_para(int *value) { *value = 66; }
4、使用函数返回值替代全局变量 不推荐如下方式读取数据: int result;void calculate(void) { result = get_state();} 推荐如下方式读取数据: int calculate(void) { return get_state();}
5、加static限制全局变量的作用域 可以在指定的源文件里定义一个带static关键词的静态全局变量,则该全局变量只能在该文件里被使用,其他文件无权访问: static int counter; 如果只是在某个源文件内部使用的变量,就一定要定义为静态变量!
6、使用局部结构体指针变量间接操作 在函数内部需要频繁操作某个全局结构体变量时,可以定义一个局部结构体指针变量,来指向这个全局结构体变量,通过操作局部结构体指针变量即可达到更新全局结构体变量的效果: typedef struct { float length; float width; float area; }st_rectangle; st_rectangle g_stRectangle; //全局结构体变量
void func(void) { //定义一个局部结构体指针变量,指向全局结构体变量 st_rectangle *pRectangle =&g_stRectangle; //…… //在函数内部操作pRectangle等同于操作g_stRectangle } 方法2和方法6相结合的应用方法,你一定要知道,它将会让你写的代码有质的飞跃!
举个作者自己开发的例子: 这样这个函数里其实就出现了一次st_loadcell_config这个全局变量; 而且如果你修改了pLoadcellConfig的成员变量,也就是直接修改了st_loadcell_config的成员变量,一箭双雕,何乐而不为?
7、使用局部变量替换全局变量 如果只是在函数内部使用的变量,就一定要定义为局部变量!
通过以上的一些方法,可以显著减少全局变量的使用,提高代码的模块化程度和可维护性。当确实需要全局变量时,可以考虑将其封装在结构体中,并通过访问函数的方式来操作,而不是直接暴露全局变量。 以上是作者的一些经验,分享出来,希望对你有所帮助。
如果你有更多更好的减少全局变量使用的方法,欢迎来贴分享和讨论!
让我们一起向全局变量满天飞的代码 say godbye!
|