6

假设我有一个像这样的简单函数:

int all_true(int* bools, int len) {
    if (len < 1) return TRUE;
    return *bools && all_true(bools+1, len-1);
}

这个函数可以用更明显的尾递归风格重写,如下所示:

int all_true(int* bools, int len) {
    if (len < 1) return TRUE;
    if (!*bools) return FALSE;
    return all_true(bools+1, len-1);
}

从逻辑上讲,两者之间的差异为零;假设bools仅包含TRUEFALSE(明智地定义),它们做的事情完全相同。

我的问题是:如果编译器足够聪明,可以将第二个优化为尾递归调用,那么考虑到“&&”短路,期望它以相同的方式优化第一个是否合理?显然,如果使用非短路运算符,这将不是尾递归,因为这两个表达式都将在运算符应用之前进行评估,但我对短路的情况很好奇。

(在我收到大量评论告诉我 C 编译器通常不优化尾递归调用之前:考虑这是一个关于使用短路运算符优化尾递归调用的一般问题,独立于语言。我会很高兴用 Scheme、Haskell、OCaml、F#、Python 重写它,或者如果你不懂 C,你会用什么别的什么东西。)

4

1 回答 1

2

您的问题实际上是“编译器有多聪明?” 但您没有说明您使用的是哪个编译器。

给定一个假设的合理编译器,它在优化之前将源代码转换为中间流图,您编写的两个代码片段都可以用相同的方式表示(&& 运算符虽然便于键入,但编译起来并不像& 运算符;所以如果它在假设的编译器的一个阶段被扩展,我不会感到惊讶)。基于这种假设,断言您的问题的答案是“是”是合理的。

但是,如果你真的要依赖它,你应该用你碰巧使用的任何编译器来测试它。

于 2011-12-15T06:47:37.647 回答