Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在SICP中,它说即使递归调用实际上是迭代的,C中的内存消耗也会增加。为什么?_C#_Java_C_Recursion_Sicp - Fatal编程技术网

C# 在SICP中,它说即使递归调用实际上是迭代的,C中的内存消耗也会增加。为什么?

C# 在SICP中,它说即使递归调用实际上是迭代的,C中的内存消耗也会增加。为什么?,c#,java,c,recursion,sicp,C#,Java,C,Recursion,Sicp,原文是 进程和过程之间的区别可能令人困惑的一个原因是,大多数通用语言(包括Ada、Pascal和C)的实现都是以这样的方式设计的,即任何递归过程的解释都会消耗随过程调用数目的增加而增加的内存量,即使描述的过程是,原则上,迭代。因此,这些语言只能通过使用特殊用途的“循环”结构(如do、repeat、until、for和while)来描述迭代过程 我不熟悉C语言,Java或C呢?他们也是这样吗? 为什么 注:我认为作者所说的是不同语言的能力。但实际上这只是编译器的不同实现。C和类似的语言通常使用a来

原文是

进程和过程之间的区别可能令人困惑的一个原因是,大多数通用语言(包括Ada、Pascal和C)的实现都是以这样的方式设计的,即任何递归过程的解释都会消耗随过程调用数目的增加而增加的内存量,即使描述的过程是,原则上,迭代。因此,这些语言只能通过使用特殊用途的“循环”结构(如do、repeat、until、for和while)来描述迭代过程

我不熟悉C语言,Java或C呢?他们也是这样吗? 为什么


注:我认为作者所说的是不同语言的能力。但实际上这只是编译器的不同实现。

C和类似的语言通常使用a来存储每个函数的本地变量。每次调用函数时,堆栈中会有更多的部分被占用;每次函数返回时,堆栈的使用都会减少


但是,智能编译器没有理由不能在适当的地方执行类似的操作,从而消除堆栈的使用。在像Lisp这样的语言中,我认为需要解释器来执行这样的优化,因此这可能是作者试图做出的区别。

C和类似的语言通常使用a来存储每个函数的局部变量。每次调用函数时,堆栈中会有更多的部分被占用;每次函数返回时,堆栈的使用都会减少


但是,智能编译器没有理由不能在适当的地方执行类似的操作,从而消除堆栈的使用。在像Lisp这样的语言中,我认为需要解释器来执行这样的优化,因此这可能是作者试图做出的区别。

他基本上是想说,这些语言的编译器不能消除尾部递归。长话短说,不管怎样,他是错的或是过度概括了——我想大多数实现都是用黄鼠狼的措辞,从技术上讲可能是正确的,尽管充其量只是误导。虽然我不能保证每个其他语言的编译器都会进行尾递归消除,但毫无疑问,至少有一些C和C++编译器,例如英特尔C++、GCC/G++可以而且会。我还没有检查过,但是GNU艾达编译器使用的是相同的优化器,如它们的C和C++编译器,我的直接猜测是它也能完成尾递归消除。
我已经很久没有使用Pascal了,所以我无法对它做出明智的评论-我的直接猜测可能是否定的,但这与语言本身没有什么关系,主要是因为目前使用Pascal的最早可以追溯到Borland,而且他们似乎从未在优化代码生成方面投入过大量精力。

他基本上是想说这些语言的编译器不能消除尾部递归。长话短说,不管怎样,他是错的或是过度概括了——我想大多数实现都是用黄鼠狼的措辞,从技术上讲可能是正确的,尽管充其量只是误导。虽然我不能保证每个其他语言的编译器都会进行尾递归消除,但毫无疑问,至少有一些C和C++编译器,例如英特尔C++、GCC/G++可以而且会。我还没有检查过,但是GNU艾达编译器使用的是相同的优化器,如它们的C和C++编译器,我的直接猜测是它也能完成尾递归消除。
我已经很久没有使用Pascal了,所以我无法对它做出明智的评论-我的直接猜测可能是否定的,但这与语言本身没有什么关系,主要是因为目前使用Pascal的最早可以追溯到Borland,而且他们似乎从未在优化代码生成方面投入过大量精力。

你问:C呢

C、 与Java类似,但与大多数C/C++或ADA实现不同的是,它编译成一种中间语言,然后再进一步编译,通常在运行时由实时编译器进行编译

在编写本文时,C编译器不会执行尾部递归消除,但JIT可能会执行


有关详细信息,请参见您提出的问题:C如何

C、 与Java类似,但与大多数C/C++或ADA实现不同的是,它编译成一种中间语言,然后再进一步编译,通常在运行时由实时编译器进行编译

在编写本文时,C编译器不会执行尾部递归消除,但JIT可能会执行


有关详细信息,请参见

它与编译器的实现无关

你已经错过了他试图提出的要点,即过程和程序之间的区别。公关
过程可能是递归的,即使它所实现的底层过程原则上是迭代的;递归过程消耗堆栈。

它与编译器的实现无关


你已经错过了他试图提出的要点,即过程和程序之间的区别。一个过程可能是递归的,即使它所实现的底层过程在原则上是迭代的;递归过程消耗堆栈。

实际上,它并没有说它们是迭代的。它说…原则上,是迭代的。因此,它们仍然是递归的,并且有额外过程调用的开销。实际上,它并没有说它们是迭代的。它说…原则上,是迭代的。因此,它们仍然是递归的,并且有额外过程调用的开销。lisp和scheme没有调用堆栈吗?@崔鹏飞:我对lisp的实现不太了解;但我似乎记得读到过这样一篇文章,语言要求解释器进行尾部调用优化。所以作者所说的只是编译器的不同实现,而不是不同语言的能力,对吧?@崔鹏飞:也许吧。我想象一下,当SICP在20世纪80年代初首次编写时,C/C++编译器远不如现在那么聪明。lisp和scheme没有调用堆栈吗?@崔鹏飞:我对lisp的实现不太了解;但我似乎记得读到过这样一篇文章,语言要求解释器进行尾部调用优化。所以作者所说的只是编译器的不同实现,而不是不同语言的能力,对吧?@崔鹏飞:也许吧。我可以想象,当SICP在20世纪80年代初首次编写时,C/C++编译器的智能程度远远低于现在。因此,作者所说的只是编译器的不同实现,而不是不同语言的能力,对吗?@崔鹏飞:是的,差不多。我的看法与他所做的相反:因为Scheme和Lisp通常非常依赖递归,所以消除尾部递归对于所有实现都是必不可少的。因为Pascal、Ada、C等可以直接表示迭代,所以对它们来说就不那么重要了。@JerryCoffin:Common Lisp不能保证尾部递归省略,即使许多CL编译器确实这样做了。优化尾部调用是scheme的基础,因为没有其他方法可以生成循环。所以作者所说的只是编译器的不同实现,而不是不同语言的能力,对吗?@崔鹏飞:是的,差不多。我的看法与他所做的相反:因为Scheme和Lisp通常非常依赖递归,所以消除尾部递归对于所有实现都是必不可少的。因为Pascal、Ada、C等可以直接表示迭代,所以对它们来说就不那么重要了。@JerryCoffin:Common Lisp不能保证尾部递归省略,即使许多CL编译器确实这样做了。优化尾部调用是scheme的基础,因为并没有其他方法来生成循环。