如何让 gcc 编译器不优化像 printf 这样的标准库函数调用?

How to get the gcc compiler to not optimize a standard library function call like printf?

出于好奇,我想知道是否有任何方法可以让 gcc 不优化任何函数调用?

在生成的汇编代码中,printf函数被putchar替换。即使使用默认的 -O0 最小优化标志也会发生这种情况。

#include <stdio.h>

int main(void) {
    printf("a");
    return 0;
}

Godbolt 显示 GCC9 正在做,clang8 保持不变。)

使用 -fno-builtin 禁用标准 C 函数的所有替换和内联。

或使用 -fno-builtin-FUNCNAME 作为特定功能,例如 -fno-builtin-printf

默认情况下,一些 commonly-used 标准 C 函数作为内置函数处理,类似于 __builtin_popcount。如果可能,printf 的处理程序将其替换为 putchar 或 puts。 https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html

默认情况下,像 printf("a") 这样的 C 语句的实现细节不被视为可见的 side-effect,因此不会被保留。您仍然可以在 call-site 处设置断点并进入函数(至少在 asm 中,或者如果安装了调试符号,则在源代码模式下)。


要禁用单个函数的其他类型的优化,请参阅 __attribute__((optimize(0))) on a function#pragma GCC optimize。但要注意:

The optimize attribute should be used for debugging purposes only. It is not suitable in production code.


您无法禁用所有 优化。一些优化是 gcc 通过内部表示转换为 asm 的方式所固有的。参见 Disable all optimization options in GCC

例如即使在 -O0 gcc 也会将 x / 10 优化为乘法逆。

它仍然将 C 语句之间的所有内容存储到内存中(为了一致的调试;that's what -O0 really means); gcc 没有 "fully dumb" 模式试图尽可能天真地将 C 音译为 asm。为此使用 tcc-O0 的 Clang 和 ICC 比 gcc 更直白一些,MSVC 调试模式也是如此。

请注意,-g 对 code-gen 没有 任何 影响,仅对发出的元数据有影响。 GCC 使用其他选项(主要是 -O-f*-m*)来控制 code-gen,因此您始终可以安全地启用 -g 而不会影响性能,除了更大的二进制文件。这不是 debug mode(即 -O0),它只是 debug symbols.