Ackermann的功能在gcc上有段落错误

时间:2013-04-24 00:08:56

标签: c gcc

很明显我不是C的主管作家,但是想知道,与这个问题相关Ackermann very inefficient with Haskell/GHC(这可能让我感到非常不理智)为什么作者的计划要计算Wilhelm Ackermann的着名功能:

int ack(int m, int n) {
  if (m == 0) return n+1;
  if (n == 0) return ack(m-1, 1);
  return ack(m-1, ack(m, n-1));
}

int main() {
  printf("%d\n", ack(4,1));
  return 0;
}

工作正常,但是当给出一个明显的优化(这有助于其他地方)并给出参数(4,2) - 当然在算法上是残忍的 - 以Segmentation fault: 11结尾:

int ack(int m, int n) {
  if (m == 0) return n+1;
  if (m == 1) return n+2;
  if (n == 0) return ack(m-1, 1);
  return ack(m-1, ack(m, n-1));
}

int main() {
  printf("%d\n", ack(4,2));
  return 0;
}

如果我注释掉“优化”行if (m == 1) return n+2;,该程序会像在其他语言中一样运行,但不会产生相同的效果 - 至少在运行5分钟后不会。 [校正,似乎确实如此 - 在8分41秒之后](我应该注意到我使用的是带有os x的gcc,但是同样的情况似乎发生在例如gcc-4.7.2 ideone.com上。)

我同意该程序甚至不值得编译,但是想知道为什么在我熟悉的其他语言中通常被视为恐怖和作为语言缺陷或编译器错误的分段错误在这里是适当的响应对于gcc

1 个答案:

答案 0 :(得分:5)

两个程序都没有堆栈,你的改进速度更快。请注意,所需的堆栈与参数'n'成正比,'n'快速增长。所以没有错误,只是一台有限的机器。

让我从我的档案中添加一些代码,只是为了好玩和更快。它还表明'n'每增加一个'm',它的增长速度有多快。

typedef unsigned long long N;
N acker (N m, N n)
{
        while (1)
        switch (m)
        {
        case 0: return n+1U;
        case 1: return n+2U;
        case 2: return 2U*(n+1U)+1U;
        case 3: return (1LLU<<(n+3U))-3U;
        default:
                if (n == 0U)
                        n = 1U;
                else
                        n = acker(m, n-1U);
                m--;
                break;
        }
        return n+1U;
}