dsi*_*cha 32 c standards tail-recursion tail-call-optimization
我经常听到人们说C不执行尾部呼叫消除.虽然标准不能保证,但是无论如何,它是否在实践中通过任何体面的实现来执行?假设你只针对成熟的,实现良好的编译器而不关心为模糊平台编写的原始编译器的绝对最大可移植性,那么在C中依赖尾调用是否合理呢?
另外,将尾部呼叫优化留在标准之外的理由是什么?
AnT*_*AnT 28
像"C不执行尾部调用消除"这样的语句没有任何意义.正如你自己正确地指出的那样,这样的事情完全取决于实现.是的,任何体面的实现都可以轻松地将尾递归转换为[相当于]一个循环.当然,C编译器通常不会对优化程序以及每个特定代码段中不会发生的优化提供任何保证.你必须编译它并亲自看看.
虽然现代编译器可以在开启优化时进行尾部调用优化,但是调试版本可能会在没有它的情况下运行,因此您可以获得堆栈跟踪和进入/退出代码以及类似的奇妙事情.在这种情况下,不希望尾调用优化.
由于尾调用优化并不总是令人满意,因此将其强制命令编译器编写器是没有意义的.
我认为,只有在预期或需要大量递归的情况下,才需要保证尾部调用优化。也就是说,使用鼓励或强制执行功能性编程风格的语言。(使用这些类型的语言,您可能会发现不鼓励for或while不鼓励使用循环,或者将循环视为不优雅的语言,或者甚至完全不鼓励使用循环,因此出于所有这些原因,您可能会求助于递归,甚至更多。)
显然,C编程语言(IMHO)在设计时并未考虑函数式编程。有各种循环结构一般用于支持递归:for,do .. while,while。用这种语言,在标准中规定尾部调用优化没有多大意义,因为并不严格要求保证工作程序。
再次将它与没有while循环的功能编程语言进行对比:这意味着您将需要递归;反过来,这意味着该语言必须确保在多次迭代中,堆栈溢出不会成为问题;因此,这种语言的官方标准可能会选择规定尾部呼叫优化。
PS:请注意我的观点略有瑕疵的尾调用优化。到最后,我提到堆栈溢出。但是谁说函数调用总是需要堆栈呢?在某些平台上,函数调用可能以完全不同的方式实现,并且堆栈溢出甚至都不会成为问题。这将是反对在标准中规定尾部调用优化的另一个论点。(但是请不要误会我的意思,即使没有堆栈,我也可以看到这种优化的优点!)