使用 gcc 编译程序时,大小会偏大,本文将介绍一些基本方法来减小程序的大小
1. 使用 -Os
和 -flto
gcc 有很多优化等级,其中
-O0-O1
: 只进行必要的优化,方便 gdb 调试
-O2~O3
: 重点优化代码执行速度,不考虑代码大小
-Os
: 重点优化代码大小
要优化大小,必须选择 -Os
优化,在本插件中,勾选:

某些时候 -Os
效果也不理想,这个时候可以同时开启 gcc 的 -flto
(Linker Time Optimization),方法:
在 C Compiler Options
里加入 -flto
,保存即可

该功能将在链接时,站在全局角度对整个程序进行优化,该功能的缺点是程序将被合并和内联,将难以进行 gdb 调试
注意事项:
- 不要使用
-flto
优化含有中断向量的 .c 文件 (xxx_startup.c)
- 不要使用
-flto
优化含有 xxx_IRQ_Handler 函数定义的 .c, 典型的比如:stm32fxx_it.c
- 不要使用
-flto
优化 .s 汇编文件
- 不要使用
-flto
优化同时含有 weak
和 alias
符号的 .c 文件,并在链接器选项中,调整该文件的 obj 链接次序,将 order 优先级调整为较小值(比如 0
),目的是将其放在最前面进行链接,避免 weak 符号失效
上述不能进行 lto 的文件,需要单独为该源文件添加 -fno-lto
参数以禁用lto优化,操作方法如下:

2. 减少双精度软件浮点的使用,尽可能使用单精度浮点
如果你的 mcu 不带硬件浮点,并且你的程序使用了软件浮点,尽可能使用单精度浮点:
在程序中使用 float32,float
而不是 double
使用 math 库时,使用带 f
的 float 版本
在浮点常量表达式使用 f
后缀,比如:#define PI 3.14f
本例中,仅将程序中唯一一处双精度浮点的语句更正为 单精度
,大约节省 3KB 代码空间:


如何判断程序是否使用双精度浮点?以及定位问题语句位置
编译结束后,打开 .map
文件,搜索 __aeabi_d
字样即可查看是否存在双精度浮点符号的使用
如果发现相关符号,打开项目的 Output Files
,点击 ELF 文件并打开,然后右键菜单反汇编整个程序:
在其中搜索 __aeabi_d
字样,即可定位问题语句在源程序中的位置

3. 标准库,少用 scanf
scanf 类的库函数(如:scanf(), sscanf() ...)将占用较大空间,若要使用匹配特定的字符串模式,建议手写
本例中,移除仅有的一处 scanf
,大约可节省 2KB 空间:


总结
推荐方法一:使用 -Os
+ -flto
,多数情况下效果显著,操作起来也比较简单。
其他方法的话,需要修改程序来进行优化,如果程序比较复杂的话,可能比较麻烦