4

尾调用优化是否适用于对返回 void 的函数的递归调用?例如我有一个函数void fun()

void fun()
{
    ...
    ...
    ...
    fun();
}

这里编译器不会知道,调用 fun() 是最后一条语句。那么尾调用优化是否只针对返回一些值的函数?

4

1 回答 1

2

答案是肯定的,它可以,但编译器没有义务这样做。是否这样做在很大程度上取决于函数、编译器和选择的优化级别。如果您担心特定函数的这一点,请查看特定编译器在特定优化级别生成的程序集。

更具体地说,GCC(至少是使用 LLVM 作为后端的 Apple 版本)将为至少一些返回void优化级别-O1或更高级别的函数生成尾调用优化代码。

一些测试代码:

/* Fills an array with a single value, recursively with side effects */
void fillarray(int val, int* curr, int* end)
{
  if (curr==end) return;

  *curr = val;
  fillarray(val,curr+1,end);
}

使用最少的优化 ( -O1),编译为程序集 ( gcc -O1 -S test.c) 会产生一个很好的尾调用优化函数:

_fillarray:
        pushq       %rbp
        movq        %rsp, %rbp   # set up the stack

        cmpq        %rdx, %rsi   # early exit if beg == end
        je  LBB1_2
LBB1_1:
        movl        %edi, (%rsi) # *curr = val
        addq        $4, %rsi     # curr++

        cmpq        %rsi, %rdx   # TAIL CALL optimization is here
        jne LBB1_1               # if curr != end, go to LBB1_1
LBB1_2:
        popq        %rbp         # restore the stack and exit
        ret

(注意:我已经删除了一些不必要的标签和对齐语句,它们会混淆程序集的结构)。

此外,当关闭优化 ( -O0) 时,生成的代码是递归的(不是尾调用优化的)。

于 2013-06-16T20:21:10.837 回答