"兄弟电话"是什么意思?

bua*_*agg 18 c++ gcc tail-recursion compiler-optimization

关于GCC手册,

-foptimize同胞通话

优化兄弟和尾部递归调用.

例如,我知道尾递归调用

int sum(int n){return n == 1?1:n + sum(n-1); }

然而,兄弟姐妹的意思是什么?

Tan*_*til 14

尾调用

如果函数调用是在另一个函数中执行的最后一个动作,则称其为尾调用。

名称源于函数调用出现在其他函数的尾部位置。

int foo(int a, int b) {
    // some code ...
    return bar(b);    // Tail call which is neither sibling call nor tail recursive call.
}
Run Code Online (Sandbox Code Playgroud)

bar 出现在尾部位置 foo。Call tobar是尾调用。


尾递归调用

尾递归调用是尾调用的一种特殊情况,其中被调用函数与调用函数相同。

int foo(int a, int b) {
    if (a > 0) {
        return foo(a - 1, b + 1);    // Tail recursive call
    } else {
        return b;
    }
}
Run Code Online (Sandbox Code Playgroud)

兄弟姐妹的呼唤

同级调用是尾调用的另一种特殊情况,其中调用者函数和被调用者函数不需要相同,但它们具有兼容的堆栈占用空间。

这意味着两个函数的返回类型必须相同,并且传递的参数必须占用相同的堆栈空间。

int foo(int a, int b) {
    // some code ...
    return bar(a - 1, b);    // Sibling call, also a tail call, but not a tail recursive call.
}
Run Code Online (Sandbox Code Playgroud)

每个尾递归调用都是一个兄弟调用,因为定义意味着每个函数都是它自己的兄弟。


为什么要区分?

由于相同的堆栈占用空间,更换堆栈框架变得相对容易。编译器编写者不必调整堆栈帧的大小,并且就地突变变得很简单。


Jav*_*ier 7

它必须是这样的:

int ispair(int n) { return n == 0 ? 1 : isodd(n-1); }
int isodd(int n) { return n == 0 ? 0 : ispair(n-1); }
Run Code Online (Sandbox Code Playgroud)

一般来说,如果函数调用是最后一句,那么可以用跳转代替。

void x() { ......; y(); }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,y()可以用跳转(或内联函数)代替标准函数调用代替。

  • 这与尾调用优化有何不同? (3认同)

Sam*_*son 5

如果两个函数共享相同的返回类型结构等效项,并且匹配其参数的空间要求,则编译器会将其视为同级函数。

http://www.drdobbs.com/tackling-c-tail-calls/184401756