在 gcc 生成 asm 代码的阶段,内联函数被其代码替换。
将内联用于递归函数时会发生什么行为
inline int fact (int n)
{
if (n<=1)
return 1;
else
return (n * fact(n-1));
}
gcc -S
当递归函数带有inline
前缀和递归函数没有前缀时,我生成了 asm 代码inline
,我发现这两种情况的 asm 代码是相同的。
你对此有什么解释吗?
请注意,这inline
只是对编译器可能接受或不接受的编译器的建议。遵守您的建议对编译器没有约束力。即使没有建议,智能编译器也会内联函数。通常,对于递归函数,编译器会做到一定的深度。
为什么编译器没有
inline
你的函数?
对于递归函数,编译器通常会寻找机会执行尾调用优化。您的函数不是尾调用 recursive。
是inline
的:实际上并没有告诉编译器它必须内联函数。它唯一需要的效果是告诉链接器该函数可以在多个目标文件中定义。(没有inline
,那将是链接时错误。)
这允许您将函数定义存在于多个翻译单元中,以便编译器可以选择内联函数,而不会产生链接器错误。现代编译器在决定是否内联函数时可能会或可能不会考虑关键字的存在。inline
无论如何都必须编译每个内联函数,以防有人需要指向该函数的指针。要检查差异,您应该在这样的地方使用该函数:
inline int fact (int n)
{
if (n<=1)
return 1;
else
return (n * fact(n-1));
}
void main () {
printf("%d\n", fact(2));
}
正如其他人已经说过的,inline
这只是一个提示,而不是一个指令。编译器对内联函数有最终决定权。如果您想强制内联某些内容,可以使用宏来完成。但就我而言,你不能有递归宏,所以这是一条死胡同。
话虽如此,即使您可以强制内联函数,您也应该知道(在任何优化级别)编译器可以将一些递归函数展开为普通的 while 循环,因此您不会在最终程序集中看到任何悖论:生成的循环只会被内联。