正文
大家好,我是bug菌~
一谈到编译器的优化等级,很多人都会潜意识的认为:"一定不要开优化,否则会产生意想不到的问题~",于是就这样口口相传,使得很多后来的学习爱好者都会有意的去回避掉优化等级这个问题。
优化其实是多个方面的,就像我们平时不同的人写一个功能模块的代码,有些人写出来的代码运行效率高、可是代码量大;而有些人写出来的代码效率一般,但是比较简洁有效等等。
如何选择优化选项也是类似的,编译器会根据你的优化选项内容,按照一定的规则和策略来优化你的代码,比如代码中存在较多无效的逻辑语句,如果不进行优化,那么编译器几乎会根据你所写的语句一步一步进行“翻译”成汇编来执行,这样的运行效率是很慢的,好在现在大部分编译器即使你不开优化等级,也会对你的代码进行或多或少的优化处理。
设置了对应的优化等级,编译器会根据你所选择的优化等级,对你的代码进行不同程度的分析,最终从不同的维度来进行优化处理(如代码大小、资源的占用、执行性能等)。
那么很多掉过坑的朋友该说了,“有一次编译器开启了优化,不是按照我所编写的逻辑来运行的,于是从那以后我就习惯了不开优化”。
其实通常编译器相对我们而言,更加的了解处理器,对于前面那位朋友的问题,更多的还是因为对所用的编译器不够熟悉,编写的代码让编译器"误解"了你的意思,不能完全赖在优化上。
还是那句话:"存在即合理",编译器也仅仅只是一个工具,不要因为驾驭不了,就持否定的态度。
反而你所编写的代码如果经不住各种优化等级的考验,是不是可以从侧面反映出当前代码的设计不合理?不够规范?考虑得不够全面呢?
实际项目中让程序代码在所有优化等级下都可以正常运行来检查各种奇葩问题,也是一种检验代码健壮性的有效手段。
GCC毕竟是嵌入式领域广泛应用的编译器,下面便以GCC编译器为例讲解一下相关优化选项:(其他编译器略有差异,注意区分)
1
GCC的优化选项
通常我们使用到-Ox选项,其中x有:0、1、2、3等,随着数值的增加,优化的程度也是逐步增加。
-O0通常是不对代码进行优化,或者是最简单的一些优化,跟源码执行顺序基本是一致的,也比较方便单步调试,所以其不需要过多的分析代码,编译速度也是相当快的,debug阶段通常用该优化项,等代码稳定以后,再考虑其他的优化项。
-O1主要是一些基础类的优化,比如删除一些无效的代码、展开内联函数等,能够在一定程度上提高运行效率。
-O2在O1基础上进一步优化,比如循环优化、函数跳转优化等,编译相对较长,且代码的大小也会有一定增加。
-O3在O2基础上更进一步优化,比如循环展开、向量化等。
通常使用-O3优化较少,因为其优化程度较高,带来的逻辑风险也相应的提高,而-O2是一种比较折中的选项,基本满足要求,且比较安全可靠。
除了上面常见的集中,当然你也可以使用其他更加精细化的选项,来自己控制优化的内容,具体就要参考GCC的相关手册来了解使用了。
2
GCC部分代码设置编译选项
有时候一套代码中有部分代码需要进行不一样的优化策略处理,那么通常编译器可以设置某些函数进行优化、或者某些文件进行优化的设置等。
下是GCC部分代码使用固定的-O0进行优化
#pragma GCC push_options
#pragma GCC optimize ("O0")
void foo(void)
{
/* Do something, but don't optimize this function */
}
#pragma GCC pop_options
当然,如果当你怀疑相关问题与优化等级的选择相关,可以采用这种方式,把部分可以代码进行非优化状态来运行,从而缩小问题的排查范围。
3
优化等级越高越不好调试
特别是玩单片机的同志们,习惯了使用调试器来进行单步调试,如果你想让代码编译以后易于调试,那么编译后的执行逻辑与源码所编写的执行逻辑基本上要吻合,此时代码就不能有优化处理了。
所以如果你是为了获得更高的性能、更小的代码空间、甚至是编译时间,我们会选择进行优化,必然就会牺牲易于调试这一点。
这也是很多朋友开了优化等级以后,单步调试断点到处乱跳的原因。
所以通常我们在前期调试的时候不使用任务优化选项,而到了需要进一步优化代码大小、效率等以后再考虑开启优化等级。
4
两个C关键字特别重要
1. volatile 关键字
volatile 关键字能够阻止编译器的过度优化,可以做到如下两件事情:
· 阻止编译器为了提高速度将一个变量缓存到寄存器而不写回;
· 阻止编译器调整操作 volatile 变量的指令顺序;
2. register 关键字
将代码放在寄存器的方式是使用 register 修饰变量,适用于频繁调用的变量。
最后
好了,优化等级就跟大家聊这么多吧,如果你觉得有所收获,一定记得点个赞~
bug菌唯一、永久、免费分享嵌入式技术知识平台~
推荐专辑 点击蓝色字体即可跳转
☞ MCU进阶专辑
☞ 嵌入式C语言进阶专辑
☞ “bug说”专辑
☞ 专辑|Linux应用程序编程大全
☞ 专辑|学点网络知识
☞ 专辑|手撕C语言
☞ 专辑|手撕C++语言
☞ 专辑|经验分享
☞ 专辑|电能控制技术
☞ 专辑 | 从单片机到Linux