尾递归在C语言上真的厉害吗?
Is Tail recursive really powerful on C language?
我认为 Tail-recursive 对函数式编程语言很有帮助。
C呢?
- C语言或编译器是否支持尾调用消除?
- 程序是否为新调用创建新的堆栈帧?
来自维基:
Tail calls can be implemented without adding a new stack frame to the
call stack. Most of the frame of the current procedure is not needed
any more, and it can be replaced by the frame of the tail call,
modified as appropriate (similar to overlay for processes, but for
function calls).
The program can then jump to the called subroutine. Producing such
code instead of a standard call sequence is called tail call
elimination.
C 标准和编译器都不必支持尾递归。编译器是否支持尾递归由实现定义。
尾递归通常用在函数式语言中,因为它是在结构上实现循环的自然方式,而在过程语言中实际上并没有那么多递归。
因此过程语言不需要它。但是,由编译器决定是否找到这样的优化。
C 标准根本没有将尾递归指定为语言的一部分。 C99 标准关于递归函数调用的唯一说法是:
6.5.2.2 Function Calls
11 Recursive function calls shall be permitted, both directly and indirectly through any chain
of other functions.
如果编译器可以检测尾递归并将递归调用转换为尾递归,它可以但标准并不要求这样做。
ANSI(标准)C 不需要尾递归。大多数 C 编译器都实现了它,因为优化不是很复杂,而且它在堆栈和缓存内存方面提供了巨大的节省。
Pre-ANSI,但是,C 绝对 支持尾递归。这是用 goto
:
完成的
fact(n,m) { m =+ n; n--; if(n) goto fact; return n; }
注意其他奇怪之处:+=
被拼写为 =+
并且 int
是所有变量的默认值。 pre-ansi C 的源代码示例现在并不常见,但 v6 ed.c 特别使用此方法进行错误处理。
我认为 Tail-recursive 对函数式编程语言很有帮助。 C呢?
- C语言或编译器是否支持尾调用消除?
- 程序是否为新调用创建新的堆栈帧?
来自维基:
Tail calls can be implemented without adding a new stack frame to the call stack. Most of the frame of the current procedure is not needed any more, and it can be replaced by the frame of the tail call, modified as appropriate (similar to overlay for processes, but for function calls).
The program can then jump to the called subroutine. Producing such code instead of a standard call sequence is called tail call elimination.
C 标准和编译器都不必支持尾递归。编译器是否支持尾递归由实现定义。
尾递归通常用在函数式语言中,因为它是在结构上实现循环的自然方式,而在过程语言中实际上并没有那么多递归。
因此过程语言不需要它。但是,由编译器决定是否找到这样的优化。
C 标准根本没有将尾递归指定为语言的一部分。 C99 标准关于递归函数调用的唯一说法是:
6.5.2.2 Function Calls
11 Recursive function calls shall be permitted, both directly and indirectly through any chain of other functions.
如果编译器可以检测尾递归并将递归调用转换为尾递归,它可以但标准并不要求这样做。
ANSI(标准)C 不需要尾递归。大多数 C 编译器都实现了它,因为优化不是很复杂,而且它在堆栈和缓存内存方面提供了巨大的节省。
Pre-ANSI,但是,C 绝对 支持尾递归。这是用 goto
:
fact(n,m) { m =+ n; n--; if(n) goto fact; return n; }
注意其他奇怪之处:+=
被拼写为 =+
并且 int
是所有变量的默认值。 pre-ansi C 的源代码示例现在并不常见,但 v6 ed.c 特别使用此方法进行错误处理。