编译器编译优化选项

-O 选项不是“随便开个加速按钮”,它是在告诉编译器:

你要多激进地帮我“重写”代码。

-O 是什么

-O = Optimization level(优化等级)

常见:

-O0
-O1
-O2
-O3
-Os
-Og
-Ofast

数字越大 ≠ 一定越好。有时候越大越容易炸。

各级别

-O0 默认

适合:开发调试阶段

运行效率基本等于“解释执行体验”

-O1

比 -O0 快很多,但不会太激进。

-O2 生产常用

这是默认推荐级别

会做:

优点:

大多数服务器程序都用 -O2。

-O3

在 -O2 基础上:

可能:

不是魔法,只是 更敢乱动你的代码。

-Os

优化目标:代码体积最小

适合:

会避免代码膨胀,比如过度内联。

-Og

专门为调试设计。

比 -O0 更合理,但不会把变量优化到消失。

现代项目推荐

-Ofast 危险选项

相当于:

-O3 + 允许违反标准

包括:

举例:

if (x != x)

正常是NaN检测, -Ofast 可能直接优化成false。

因为编译器假设“浮点不会是NaN”。

用在:

不用在:

优化到底做了什么

举个例子:

int add(int a)
{
    return a + 1;
}

-O0:

真的生成函数调用

-O2:

直接内联成

a + 1

再看:

for(int i = 0; i < 1000000; ++i)
{
    sum += i;
}

-O3可能:

编译器比你算得快。

优化带来的坑

UB会被放大

比如

int x;
if (x == 0)

未初始化变量。

-O0 可能还能“正常跑”。

-O2 会直接假设,UB不存在,然后把逻辑改写。

调试错乱

你打断点:

不是调试器疯了,是优化生效了。

volatile 与 内存模型问题

优化会:

多线程代码如果没写对,-O2 会帮你暴露问题。

真实工程建议

如果你做 .so:

Debug版本

-g -Og

Release版本

-O2 -DNDEBUG

如果做高性能计算

-O3 -march=native

别一上来就 -Ofast,那是给性能有执念的人准备的。

几个常用搭配

-march=native // 使用当前CPU指令集
-flto // 链接时优化
-fno-exceptions
-fno-rtti

尤其:

-flto

能跨文件优化。有时候比 -O3 更明显。

终极现实

优化等级不是“性能按钮”。

真正影响性能的:

-O3 救不了 O(n²)。