【问题标题】:What does "sibling calls" mean?“兄弟电话”是什么意思?
【发布时间】:2014-03-29 00:53:59
【问题描述】:

在 GCC 手册中,

-foptimize-sibling-calls

优化兄弟和尾递归调用。

例如,我知道尾递归调用

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

但是,兄弟调用是什么意思?

【问题讨论】:

  • First Google hit 显然有一些信息
  • 实际上,GCC 是“tail”的同义词(他们在内部文档中将其称为 a.k.a.tail)。形式上,some function具有相同大小的返回类型和具有相同总字长的参数列表。因此,例如int foo(char, char) 和 int bar(short) 将是兄弟姐妹,并且可以进行尾部优化(因此 foo 调用 bar 而调用 foo 原则上会起作用)。
  • @AngewisnolongerproudofSO 这个问题是谷歌第一个搜索“兄弟调用函数含义”的问题,所以它也应该有一些信息。

标签: c++ gcc compiler-optimization tail-recursion


【解决方案1】:

尾调用

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

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

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

bar 出现在foo 的尾部位置。对bar 的调用是尾调用。


尾递归调用

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

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

兄弟调用

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

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

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.
}

每个尾递归调用都是兄弟调用,因为定义暗示每个函数都是自身的兄弟。


为什么要区分?

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

【讨论】:

    【解决方案2】:

    编译器 如果两个函数共享相同,则将它们视为兄弟 返回类型的结构等价,以及匹配空间 他们的论点的要求。

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

    【讨论】:

      【解决方案3】:

      一定是这样的:

      int ispair(int n) { return n == 0 ? 1 : isodd(n-1); }
      int isodd(int n) { return n == 0 ? 0 : ispair(n-1); }
      

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

      void x() { ......; y(); }
      

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

      【讨论】:

      • 这与尾调用优化有何不同?
      猜你喜欢
      • 2016-10-12
      • 2015-03-13
      • 2014-12-12
      • 1970-01-01
      • 2011-10-15
      • 1970-01-01
      • 1970-01-01
      • 2011-08-12
      • 2017-06-11
      相关资源
      最近更新 更多