c - 我怎样才能让 GCC 编译器不优化像 'printf' 这样的标准库函数调用?

标签 c gcc assembly x86 compiler-optimization

有没有办法让 GCC 不优化任何函数调用?

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

#include <stdio.h>

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

(Godbolt 显示 GCC 9 正在执行此操作,而 Clang 8 保持不变。)

最佳答案

使用-fno-builtin禁用标准 C 函数的所有替换和内联。 (这对于假定 memcpy(x,y, 4) 将编译为未对齐/别名安全加载而不是函数调用的代码的性能非常不利。并禁用常量传播,例如strlen 的字符串文字。所以通常你会希望在实际使用中避免这种情况。)

或者使用 -fno-builtin-FUNCNAME 作为特定函数,例如 -fno-builtin-printf

默认情况下,一些常用的标准 C 函数被处理为内置函数,类似于 __builtin_popcount。 printf 的处理程序将其替换为 putchar 或 puts 如果可能的话。
6.59 Other Built-in Functions Provided by GCC

默认情况下,printf("a") 等 C 语句的实现细节不被视为可见的副作用,因此不会保留它们。您仍然可以在调用站点设置断点并进入函数(至少在汇编中,或者如果安装了调试符号,则在源代码模式下)。


要禁用单个函数的其他类型的优化,请参阅 __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 在组装过程中通过内部表示进行转换的固有方式。参见 Disable all optimization options in GCC .

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

它仍然将 C 语句之间的所有内容存储到内存中(为了一致的调试;that's what -O0 really means); GCC 没有尝试尽可能天真地将 C 音译为汇编语言的“完全愚蠢”模式。为此使用 tccClangICC -O0 比 GCC 更直白一些,MSVC 也是如此。 Debug模式。

请注意,-g 永远不会对代码生成产生任何影响,只会对发出的元数据产生影响。 GCC 使用其他选项(主要是 -O-f*-m*)来控制代码生成,因此您始终可以安全地启用-g 不会影响性能,除了更大的二进制文件。它不是调试模式(即-O0);它只是调试符号

关于c - 我怎样才能让 GCC 编译器不优化像 'printf' 这样的标准库函数调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57062430/

相关文章:

c - 为什么在输入一些文本并按下 "enter"键 (EOF) 后 printf 语句不在这里执行?

c - 从 C 中的用户那里获取的字符串正在被加扰

c - C 中 float 据类型的格式说明符

c - 使用 "lea ($30, %edx), %eax 将 edx 和 30 相加并放入 eax

assembly - MIPS中如何将负数变为正数?

C 使用n+1维数组作为n维数组参数

c - Windows上带有c的128位整数?

c++ - arm-none-eabi-g++ 找不到 stdc++ header

c++ - 模板重载解析中的位域

c++ - CFI 指令是什么意思? (还有一些问题)