短路运算符和尾递归

发布于 2024-12-21 13:16:31 字数 733 浏览 1 评论 0原文

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

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 只包含 TRUE 或 FALSE(合理定义),它们会做完全相同的事情。

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

(在我收到大量评论告诉我 C 编译器通常不会优化尾递归调用之前:请将此视为关于使用短路运算符优化尾递归调用的一般问题,与语言无关。我将很高兴用Scheme、Haskell、OCaml、F#、Python 重写这个,或者如果你不懂C,也可以用其他什么东西来重写它。)

Let's say I have a simple function like this:

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

This function can be rewritten in a more obviously tail-recursive style as follows:

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

Logically, there is zero difference between the two; assuming bools contains only TRUE or FALSE (sensibly defined), they do exactly the same thing.

My question is: if a compiler is smart enough to optimize the second as a tail-recursive call, is it reasonable to expect it to optimize the first in the same way, given that "&&" short-circuits? Obviously, if a non-short-circuiting operator were used, this would not be tail-recursive because both expressions would be evaluated before the operator is even applied, but I'm curious about the short-circuited case.

(Before I get a flood of comments telling me that C compilers don't usually optimize tail-recursive calls: consider this to be a general question about optimizing tail-recursive calls with short-circuit operators, independent of language. I'll be happy to rewrite this in Scheme, Haskell, OCaml, F#, Python, or what the heck ever else for you if you don't understand C.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风吹短裙飘 2024-12-28 13:16:31

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

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

但是,如果您确实要依赖于此,则应该使用您正在使用的任何编译器来测试它。

Your question is really "how smart is the compiler?" but you don't state which compiler you are using.

Given a hypothetical reasonable compiler which converts source code to an intermediary flow graph before optimizations, both fragments of code that you have written could be represented in the same way (the && operator, while convenient to type, is not nearly as trivially compiled as the & operator; so I wouldn't be surprised if it gets expanded out in one phase on a hypothetical compiler). On that assumption, it is reasonable to assert that the answer to your question is "yes".

However, if you're actually going to rely on this, you should just test it with whatever compiler you happen to be using.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文