电子产业一站式赋能平台

PCB联盟网

搜索
查看: 112|回复: 1
收起左侧

嵌入式 C 语言,为什么全局变量越少越好?

[复制链接]

459

主题

459

帖子

918

积分

二级会员

Rank: 2

积分
918
发表于 2024-10-23 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师# K# v* a9 }, `9 t& p' _
关注我,一起变得更加优秀!嵌入式开发,特别是单片机os-less的程序,最易范的错误是全局变量满天飞。# a" L3 A. _& K- H
这个现象在早期汇编转型过来的程序员以及初学者中常见,这帮家伙几乎把全局变量当作函数形参来用。/ G3 [. R, o. s( X; Y& E
在.h文档里面定义许多杂乱的结构体,extern一堆令人头皮发麻的全局变量,然后再这个模块里边赋值123,那个模块里边判断123分支决定做什么。4 F# l5 m. t& g! Z% [
每当看到这种程序,我总要戚眉变脸而后拍桌怒喝。没错,就是怒喝。7 b' |6 S% ?* V! M9 G/ x" L. Q, D
不否认全局变量的重要性,但我认为要十分谨慎地使用它,滥用全局变量会带来其它更为严重的结构性系统问题。
9 v1 R; u- X* Y6 r

l1qpj01wtoc64037227745.png

l1qpj01wtoc64037227745.png
  M- D, `6 ]3 z5 I8 `6 ^
为什么全局变量要越少越好?
- ^7 D- p  A7 ?它会造成不必要的常量频繁使用,特别当这个常量没有用宏定义“正名”时,代码阅读起来将万分吃力。
' O" T" E. D. g它会导致软件分层的不合理,全局变量相当于一条快捷通道,它容易使程序员模糊了“设备层”和“应用层”之间的边界。写出来的底层程序容易自作多情地关注起上层的应用。
2 v3 b/ B. g) C. w这在软件系统的构建初期的确效率很高,功能调试进度一日千里,但到了后期往往bug一堆,处处“补丁”,雷区遍布。说是度日如年举步维艰也不为过。$ S, z( E0 I2 m
由于软件的分层不合理,到了后期维护,哪怕仅是增加修改删除小功能,往往要从上到下掘地三尺地修改,涉及大多数模块,7 e% I$ s4 f8 c: Q8 `
而原有的代码注释却忘了更新修改,这个时候,交给后来维护者的系统会越来越像一个“泥潭”,注释的唯一作用只是使泥潭上方再加一些迷烟瘴气。
4 K2 s5 ~3 D7 o全局变量大量使用,少不了有些变量流连忘返于中断与主回圈程序之间。
" u. {3 m9 _, x+ g这个时候如果处理不当,系统的bug就是随机出现的,无规律的,这时候初步显示出病入膏肓的特征来了,没有大牛来力挽狂澜,注定慢性死亡。& p' l4 f: n. X9 F  i
无需多言,您已经成功得到一个畸形的系统,它处于一个神秘的稳定状态!
3 M6 h. Q  Z* b; ~" i& @, R你看着这台机器,机器也看着你,相对无言,心中发毛。你不确定它什么时候会崩溃,也不晓得下一次投诉什么时候道理。
' \9 W* p$ }& T; E  q% E# D) `全局变量大量使用有什么后果?/ [& X" [: r) a) R1 \
“老人”气昂昂,因为系统离不开他,所有“雷区”只有他了然于心。当出现紧急的bug时,只有他能够搞定。你不但不能辞退他,还要给他加薪。
6 f2 f: m7 E8 @+ m) M+ s; b新人见光死,但凡招聘来维护这个系统的,除了改出更多的bug外,基本上一个月内就走人,到了外面还宣扬这个公司的软件质量有够差够烂。( \, u) L. X5 S  B5 r, m
随着产品的后续升级,几个月没有接触这个系统的原创者会发现,很多雷区他本人也忘记了,于是每次的产品升级维护周期越来越长,
# T7 j4 C" z. F' ~5 |1 v6 s% ^因为修改一个功能会冒出很多bug,而按下一个bug,会弹出其他更多的bug。在这期间,又会产生更多的全局变量。3 W! d' a9 q# M% \5 o: r4 K
终于有一天他告诉老板,不行啦不行啦,资源不够了,ram或者flash空间太小了,升级升级。- e3 m% g3 c# W  y6 s7 a
客户投诉不断,售后也快崩溃了,业务员也不敢推荐此产品了,市场份额越来越小,公司形象越来越糟糕。2 w; ^+ R( G% f6 y

ib1ddhqhnrt64037227845.jpg

ib1ddhqhnrt64037227845.jpg
: t2 F0 R$ m6 }& R
, X3 }  K. X; N; B) \& `# r
要问对策,只有两个原则
" ?& R, R7 a* @9 p$ d6 F能不用全局变量尽量不用,我想除了系统状态和控制参数、通信处理和一些需要效率的模块,其他的基本可以靠合理的软件分层和编程技巧来解决。
9 ~# h5 P! I) c# ~! G0 Z+ `如果不可避免需要用到,那能藏多深就藏多深。
3 H6 K+ M6 p' v5 s8 O如果只有某.c文件用,就static到该文件中,顺便把结构体定义也收进来;如果只有一个函数用,那就static到函数里面去;
6 t) F) c% @, c' L如果非要开放出去让人读取,那就用函数return出去,这样就是只读属性了;6 @4 h, ~$ @# H; ]  X2 a: K
如果非要遭人蹂躏赋值,好吧,我开放函数接口让你传参赋值;实在非要extern侵犯我,我还可以严格控制包含我.h档的对象,而不是放到公共的includes.h中被人围观,丢人现眼。
1 K( {0 }9 r6 L0 s( ]! K+ U2 {
如此,你可明白我对全局变量的感悟有多深刻,悲催的我,已经把当年那些“老人”交给我维护的那些案子加班全部重新翻写了。* a- f/ @  `; \- k5 s
最后补充
" J: u! Z/ q5 F0 z' i- n' m全局变量是不可避免要用到的,每一个设备底层几乎都需要它来记录当前状态,控制时序,起承转合。但是尽量不要用来传递参数,这个很忌讳的。5 G6 Y- K( z$ Z3 u
尽量把变量的作用范围控制在使用它的模块里面,如果其他模块要访问,就开个读或写函数接口出来,严格控制访问范围。% l) _; V# o& X
这一点,C++的private属性就是这么干的,这对将来程序的调试也很有好处。; W$ e0 H! ]0 X  h9 W. q
C语言之所以有++版本,很大原因就是为了控制它的灵活性,要说面向对象的思想,C语言早已有之,亦可实现。- Z( a! J7 k, }' w
当一个模块里面的全局变量超过3个(含)时,就用结构体包起来吧,要归0便一起归0,省得丢三落四的。5 P0 \, g8 q+ \' R& I. D
在函数里面开个静态的全局变量,全局数组,是不占用栈空间的,只是有些编译器对于大块的全局数组,会放到和一般变量不同的地址区。
% c/ d, n+ i$ s# Y, [! \若是在keil C51,因为是静态编译,栈爆掉了会报警,所以大可以尽情驰骋,注意交通规则就是了。3 _, k3 a! U/ R7 y- h" R
单片机的os-less系统中,只有栈没有堆的用法,那些默认对堆分配空间的“startup.s”,可以大胆的把堆空间干掉。
) g. \3 Q# }; i( d% \程序模型?如何分析抽象出来呢,从哪个角度进行模型构建呢?很愿意聆听网友的意见。1 a7 }$ A9 Q, J- S2 q* Z+ R
本人一直以来都是从两个角度分析系统,事件--状态机迁移图 和 数据流图,前者分析控制流向,完善UI,后者可知晓系统数据的缘起缘灭。
$ d: r5 y' \. y这些理论,院校的《软件工程》教材都有,大家不妨借鉴下。只不过那些理论,终究是起源于大型系统软件管理的,牛刀杀鸡,还是要裁剪一下的。1 q6 {7 G! g1 S' g8 f
来源:网络。
, ]! a6 }) G% E  d6 F. O1 Q-END-
6 @% T1 A+ h+ ~. l1 k  I往期推荐:点击图片即可跳转阅读' Q% m( G) I. I+ {* F
                                                        3 J' y2 ?' R  m: c% U
                                                                ; b9 z" w8 i5 W
                                                                       
  }7 m6 x! q6 B/ t                                                                               
: l, Q5 ?6 {; {$ B' s

bd0p1tudmrp64037227945.jpg

bd0p1tudmrp64037227945.jpg
4 V; _  B, s2 }: R- ?6 }2 ~( j4 \
                                                                                1 D, ?( @% }5 e9 ~# Q
                                                                                        嵌入式大佬分享,简单易用的开发工具及解决方案!! i1 {, ]" r" J. X, u7 ^
                                                        , v! v) D" Y& U! G% F% D
                                                               
, e) u. _, w2 @/ }! }" b                                                                       
" G3 {+ @8 y$ t& Z% e                                                                                : T. L% t* w' ?. `4 f% P3 \/ B9 B

bixmlpz5yfp64037228045.jpg

bixmlpz5yfp64037228045.jpg
8 G+ c$ {- m4 ^% R( r  g
                                                                                3 v& u8 K. Q8 [, s+ T& [
                                                                                        一些非常全面的嵌入式软件开发工具!
' d6 {  A$ B4 e' T' v0 G                                                               
4 x3 b& B* B: k! U: I  v& C8 s  u                                                                       
7 I: E; e3 J6 D2 C  l* S                                                                               
2 ~+ Q8 ?6 }" P' A0 J7 F. c

bpb53fw1b3y64037228145.jpg

bpb53fw1b3y64037228145.jpg
, |& ~( a& j6 u5 o+ H& [
                                                                               
, Y6 K9 w& }8 a6 D7 f                                                                                        探讨一下,嵌入式边缘计算技术,前景何在?7 r6 ~- k1 o( R, u; J
                                                                               
/ S' R2 t8 M* ]$ ~                                                                        + m% g: o$ [0 o* Y2 k/ T+ q
                                                               
6 Y: l4 n+ T& g' G                                                        我是老温,一名热爱学习的嵌入式工程师
( \* S. k! f: z' y1 h% g" M1 F关注我,一起变得更加优秀!
回复

使用道具 举报

0

主题

10

帖子

40

积分

一级会员

Rank: 1

积分
40
发表于 2024-10-24 09:50:34 | 显示全部楼层
嵌入式 C 语言受教了
回复 支持 反对

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表