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