gcc编译器使用puts切换printf调用

时间:2019-06-24 18:09:14

标签: c gcc

我已经在Ubuntu上编译了一个简单的C程序:

#include<stdio.h>

int main()
{
        printf("hello world\n");
        return 0;
}

然后我使用gdb检查了可执行文件的反汇编,然后看到了以下代码:

   0x000000000000063a <+0>:     push   %rbp
   0x000000000000063b <+1>:     mov    %rsp,%rbp
   0x000000000000063e <+4>:     lea    0x9f(%rip),%rdi        # 0x6e4
   0x0000000000000645 <+11>:    callq  0x510 <puts@plt>
   0x000000000000064a <+16>:    mov    $0x0,%eax
   0x000000000000064f <+21>:    pop    %rbp
   0x0000000000000650 <+22>:    retq

这里,编译器只是将printf调用与puts调用交换了。当我使用printf尝试此操作时,使用未添加新行的字符串对其进行调用,该调用在反汇编中仍然是对printf的调用。

我的问题是启用这种功能的编译器的机制是什么? 他是否读了要发送给printf的字符串,并且因为printf是libc函数,所以编译器可以知道他的libc来决定这种优化方式?

2 个答案:

答案 0 :(得分:3)

是的。 GCC读取并验证格式字符串,以发出有关格式字符串说明符错误的编译警告(例如,如果您使用%d但参数为unsigned int,则会打印警告。)该字符串在编译时,它还可以知道是否可以用printf()调用来代替puts()作为优化(puts()更快,因为它不必解析字符串。)

答案 1 :(得分:2)

某些函数被编译器“更好地了解”,因为它们是最常用的。 .json这种功能之一。编译器甚至会分析格式字符串,并在参数类型错误时发出警告。当编写类似的函数时,也可以通过让编译器(使用适当的属性)让函数使用printf样式格式字符串来使用此功能。并且由于知道此函数的工作原理,因此可以优化对其的调用。像这样还有许多其他功能。例如resolve: { extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'] }, 家庭成员,许多数学等