请尽量不要为全局变量赋不必要的初值!
2015-07-08 10:14
155 查看
我知道“不要为全局变量赋初值”,完全不符合大多数人遵循的编码规范。
所以此文只是一个建议,主要针对单片机工程师,因为单片机的ROM比较宝贵。如果你不理解为何要这样建议,请往下看。
如代码所示,sizetest1.c中仅定义了一个main函数,sizetest2.c中定义了一个没有初始化的全局变量,sizetest3.c定义了一个初始化了的全局变量。
我将三段代码依次编译链接成为可执行文件,可执行文件信息如下(7143,7166,107214分别为对应的可执行文件大小)
可以看得出来,相较于sizetest1.c,我定义了一个100000字节的全局变量(未作初始化),可执行文件仅增加了23个字节。而sizetest3.c,我为全局变量做了初始化,赋了初值,可执行文件就增加了近100000个字节,差不多相当于变量buffer的大小。
C语言代码在形成可执行文件之前,先编译成为汇编代码。汇编代码通常有数据段和代码段之分。我们定义的全局变量都放在数据段中。其中,作初始化的全局变量是定义在.data段中,未做初始化的全局变量定义在.bss段中。
当数据定义在.data段中时,其初始化值必须保存在可执行文件中,程序运行前,需要将初始化值赋予相应的全局变量。在.bss段中的数据,不需要做初始化(其实不然,其值一般默认初始化为0或null),可执行文件不用为其保存什么初始化数据。
所以,当我在sizetest3.c中为全局变量赋了初值,其数值大小全部保存在可执行文件中了,导致可执行文件的大小增加了差不多sizeof(buffer)字节。
当我们做单片机开发时,在初始化boot阶段,会做数据的初始化工作。数据的初始化工作主要分为两部分,一是将ROM中的全局变量初始值拷贝到RAM中的.data段中,为全局变量赋初值;二是将.bss段中的数据clear,全部填充为0。
小单片机的ROM很宝贵,好多单片机的定价是根据ROM大小来定的。为了缩减ROM的大小,我建议在单片机程序开发中,慎重对待“全局变量赋初值”,不必要的初始化全部避掉。在主函数的主循环之前,可以做一些赋初值的工作,往往在这个位置赋值也是必须的工作,如初始化一些状态标志位等。在我的单片机开发经验中,除了一些全局的状态标志位等,很少需要对全局变量赋初值。
所以此文只是一个建议,主要针对单片机工程师,因为单片机的ROM比较宝贵。如果你不理解为何要这样建议,请往下看。
1.具体示例
先给出几段示例代码。如代码所示,sizetest1.c中仅定义了一个main函数,sizetest2.c中定义了一个没有初始化的全局变量,sizetest3.c定义了一个初始化了的全局变量。
我将三段代码依次编译链接成为可执行文件,可执行文件信息如下(7143,7166,107214分别为对应的可执行文件大小)
可以看得出来,相较于sizetest1.c,我定义了一个100000字节的全局变量(未作初始化),可执行文件仅增加了23个字节。而sizetest3.c,我为全局变量做了初始化,赋了初值,可执行文件就增加了近100000个字节,差不多相当于变量buffer的大小。
2.示例分析
在分析之前,我先阐述两个概念,.data和.bss。C语言代码在形成可执行文件之前,先编译成为汇编代码。汇编代码通常有数据段和代码段之分。我们定义的全局变量都放在数据段中。其中,作初始化的全局变量是定义在.data段中,未做初始化的全局变量定义在.bss段中。
当数据定义在.data段中时,其初始化值必须保存在可执行文件中,程序运行前,需要将初始化值赋予相应的全局变量。在.bss段中的数据,不需要做初始化(其实不然,其值一般默认初始化为0或null),可执行文件不用为其保存什么初始化数据。
所以,当我在sizetest3.c中为全局变量赋了初值,其数值大小全部保存在可执行文件中了,导致可执行文件的大小增加了差不多sizeof(buffer)字节。
3.编程建议
单片机中的memory分为ROM和RAM,执行代码放在ROM中,初始化了的全局变量和没有初始化的全局变量放在RAM中,而初始化了的全局变量的初始化值放在ROM中,这样执行代码和全局变量的初始化值绑在一起,成为了可执行文件的大部分。当我们做单片机开发时,在初始化boot阶段,会做数据的初始化工作。数据的初始化工作主要分为两部分,一是将ROM中的全局变量初始值拷贝到RAM中的.data段中,为全局变量赋初值;二是将.bss段中的数据clear,全部填充为0。
小单片机的ROM很宝贵,好多单片机的定价是根据ROM大小来定的。为了缩减ROM的大小,我建议在单片机程序开发中,慎重对待“全局变量赋初值”,不必要的初始化全部避掉。在主函数的主循环之前,可以做一些赋初值的工作,往往在这个位置赋值也是必须的工作,如初始化一些状态标志位等。在我的单片机开发经验中,除了一些全局的状态标志位等,很少需要对全局变量赋初值。
相关文章推荐
- 两种启动监听器ApplicationListener和ServletContextListener
- 用来处理日常事务的 Linux 程序
- 7月初“.我爱你”域名市场报告: 阿里云获双料冠军
- android:sharedUserId问题解析
- OC对象给分类添加属性
- Hadoop集群系列(目录)
- Python中文字符问题
- 三、openCV学习笔记(Image Processing)
- 【rman,1】经典案例增量备份
- Application_Start 多次启动问题
- iphone4s从8.x.x降级到6.1.3变成可能
- js读取xml文件
- Python写入CSV文件的方法
- 整合Struts2与Spring的步骤
- 把word文档内容转换为pdf格式经验分享
- Windows 10正式版核心应用迎来新一轮更新
- Selenium WebDriver 中鼠标和键盘事件分析及扩展
- 【Unity3D】 DoTween实现飘字的效果
- 大海教你学手游2015CocosLua第一季_01环境搭建与场景封装
- MYSQL导入导出.sql文件