C尾部调用优化

C尾部调用优化,c,standards,tail-recursion,tail-call-optimization,C,Standards,Tail Recursion,Tail Call Optimization,我经常听到人们说C不执行尾部调用消除。尽管标准没有保证,但在实践中,它不是通过任何合适的实现来实现的吗?假设您只针对成熟的、实现良好的编译器,而不关心为晦涩平台编写的原始编译器的绝对最大可移植性,那么在C中依赖尾部调用消除是否合理 另外,将尾部调用优化排除在标准之外的理由是什么?像“C不执行尾部调用消除”这样的语句毫无意义。正如您自己正确指出的,类似这样的事情完全取决于实现。是的,任何合适的实现都可以很容易地将尾部递归转化为一个循环。当然,C编译器通常不会对每段特定代码中的哪些优化和哪些优化不会

我经常听到人们说C不执行尾部调用消除。尽管标准没有保证,但在实践中,它不是通过任何合适的实现来实现的吗?假设您只针对成熟的、实现良好的编译器,而不关心为晦涩平台编写的原始编译器的绝对最大可移植性,那么在C中依赖尾部调用消除是否合理


另外,将尾部调用优化排除在标准之外的理由是什么?

像“C不执行尾部调用消除”这样的语句毫无意义。正如您自己正确指出的,类似这样的事情完全取决于实现。是的,任何合适的实现都可以很容易地将尾部递归转化为一个循环。当然,C编译器通常不会对每段特定代码中的哪些优化和哪些优化不会发生提供任何保证。您必须编译它并亲自查看。

回答您的最后一个问题:标准绝对不应该对优化做出任何声明。有些环境可能或多或少难以实现。

语言标准定义了语言的行为方式,而不是要求编译器如何实现。优化不是强制性的,因为它并不总是需要的。编译器提供了一些选项,用户可以在需要时启用优化,也可以关闭优化。编译器优化可能会影响调试代码的能力(以逐行方式将C与程序集相匹配变得越来越困难),因此仅在用户请求时执行优化是有意义的。

我认为只有在预期或需要大量递归的情况下才需要保证尾部调用优化;也就是说,在鼓励或实施函数式编程风格的语言中。(对于这类语言,您可能会发现
for
while
循环要么被强烈劝阻,要么被认为不雅观,甚至可能完全不在语言中,因此出于所有这些原因,您可能会求助于递归,甚至更多。)

C编程语言(IMHO)的设计显然没有考虑函数式编程。有各种各样的循环结构通常用于支持递归:
for
do。。while
while
。在这样一种语言中,在标准中规定尾部调用优化没有多大意义,因为它不是保证工作程序的严格要求

再次将其与没有
while
循环的函数式编程语言进行对比:这意味着您需要递归;这反过来意味着语言必须确保,经过多次迭代,堆栈溢出不会成为问题;因此,这种语言的官方标准可能会选择规定尾部调用优化



p.S.:注意我关于尾部调用优化的论点中有一个小小的缺陷。在本文的末尾,我提到了堆栈溢出。但谁说函数调用总是需要堆栈呢?在某些平台上,函数调用可能以完全不同的方式实现,堆栈溢出甚至不会成为问题。这将是反对在标准中规定尾部调用优化的另一个论点。(但别误会,即使没有堆栈,我也能看到这种优化的优点!)

尽管如果启用优化,现代编译器可能会进行尾部调用优化,但调试构建可能会在没有它的情况下运行,这样您就可以获得堆栈跟踪和代码的输入/输出以及类似的美妙事情。在这种情况下,不需要尾部调用优化


由于尾部调用优化并不总是可取的,因此将其委托给编译器编写者是没有意义的。

有些情况下,尾部调用优化可能会破坏ABI,或者至少很难以语义保留的方式实现。例如,想想共享库中独立于位置的代码:当各种不同的应用程序都依赖于相同的功能时,一些平台允许程序与库动态链接以节省主内存。在这种情况下,库被加载一次并映射到每个程序的虚拟内存中,就好像它是系统上唯一的应用程序一样。在UNIX和其他一些系统上,这是通过对库使用位置无关的代码来实现的,因此寻址是相对于偏移量的,而不是相对于固定地址空间的绝对值。然而,在许多平台上,位置无关的代码不能进行尾部调用优化。所涉及的问题是,在程序中导航的偏移量必须保存在寄存器中;在英特尔32位上,使用了被调用方保存的寄存器&nbx;
%ebx
;其他平台也遵循这一理念。与使用普通调用的函数不同,那些部署尾部调用的函数必须在分支到子例程之前恢复被调用方保存的寄存器,而不是在它们返回自身时。通常情况下,这是没有问题的,因为此时,最顶端的调用函数不关心存储在
%ebx
中的值,但位置无关代码取决于每个跳转、调用或分支命令的该值

其他问题可能是面向对象语言(C++)中的未决清理,这意味着函数中的最后一个调用实际上不是最后一个调用-清理是。因此,在这种情况下,编译器通常不会进行优化

当然,
setjmp
longjmp
也有问题,因为这实际上意味着函数可以在实际完成之前多次完成执行。很难或不可能在编译时进行优化


可能还有更多的技术原因。这些只是一些考虑因素。

对于那些喜欢通过构造证明的人,h