2个内联函数在C

时间:2019-04-08 14:22:05

标签: c gcc inline

我正在尝试学习C的更高级方面,并在尝试使用__inline__关键字时写了此内容:

#include <stdio.h>


void f(int);
void g(int);


__inline__ void f(int egg)
{
    printf("f %d\n", egg);
    g(egg);
}


__inline__ void g(int egg)
{
    printf("g %d\n", egg);
    f(egg);
}


int main()
{
    f(123);

    return 0;
}

我查看了GNU手册,发现-Winline编译器选项在无法替换标记为__inline__的函数时发出警告。

我确实早在期待警告,但是我使用gcc -ansi -pedantic -Wall -Wextra -Winline -o test test.c编译了该程序,没有警告。

我运行程序时,它在出现分段错误之前将数字打印了一整遍,大概是由于超出了递归限制。

我的问题是,gcc在这种情况下的表现如何?如果确实内联了函​​数,怎么知道它在两个函数之间进行了递归调用?

提前谢谢

2 个答案:

答案 0 :(得分:5)

https://gcc.gnu.org/onlinedocs/gcc-7.4.0/gcc/Inline.html#Inline

  

除非您为函数指定“ always_inline”属性,否则GCC不会在未优化时内联任何函数

由于编译时没有进行优化,因此gcc甚至不会尝试内联函数,因此不会收到未完成的警告。

当我使用-O -Winline编译您的代码时,我得到了警告,如预期的那样:

inline.c: In function ‘main’:
inline.c:8:17: warning: inlining failed in call to ‘f’: call is unlikely and code size would grow [-Winline]
 __inline__ void f(int egg)
                 ^
inline.c:24:5: note: called from here
     f(123);
     ^~~~~~

答案 1 :(得分:2)

根据我在goldbolt中看到的情况,这种情况下编译器足够聪明,可以理解该代码等效于无限循环(请参见下面的代码.L2)。 当递归函数为tail recursive

时,此优化是可能的

这与__inline__无关。实际上,如果删除了__inline__关键字,您将获得相同的优化效果,并且还要 gf的汇编代码,而它们永远不会call

     .LC0:
            .string "f %d\n"
    .LC1:
            .string "g %d\n"
    main:
            sub     rsp, 8
    .L2:
            mov     esi, 123
            mov     edi, OFFSET FLAT:.LC0
            xor     eax, eax
            call    printf
            mov     esi, 123
            mov     edi, OFFSET FLAT:.LC1
            xor     eax, eax
            call    printf
            jmp     .L2

以下内容将gcc__inline__的{​​{1}}关键字与g生成的程序集与(在右侧)和没有(在左侧)f关键字进行比较。 如您所见,main包含完全相同的代码。唯一的区别是您获得了gf的附加代码。enter image description here