C语言函数递归调用问题。
假如我有三个函数,fun1(),fun2(),fun3()。1.我用fun1()一直调用其它函数或者自己本身时,原来函数会不会一直存在于内存中?(PS:我经过测试,函数在...
假如我有三个函数,fun1(),fun2(),fun3()。
1.我用fun1()一直调用其它函数或者自己本身时,原来函数会不会一直存在于内存中?(PS:我经过测试,函数在调用过程中,原函数会一直存在内存中,至到。。。。。)
2.直到函数调用结束,然后逐个返回结束命令 (PS:这结束语句是方便理解用的) 或者逐个返回一个返回值。直到返回至最先开始调用的fun1()这个函数。然后结束。是不是这样?
请按照我对应的编号进行回答,这样我比较容易理解,谢谢。
就像这图。我经过测试发现在函数中调用,原函数不会在内存中释放。 展开
1.我用fun1()一直调用其它函数或者自己本身时,原来函数会不会一直存在于内存中?(PS:我经过测试,函数在调用过程中,原函数会一直存在内存中,至到。。。。。)
2.直到函数调用结束,然后逐个返回结束命令 (PS:这结束语句是方便理解用的) 或者逐个返回一个返回值。直到返回至最先开始调用的fun1()这个函数。然后结束。是不是这样?
请按照我对应的编号进行回答,这样我比较容易理解,谢谢。
就像这图。我经过测试发现在函数中调用,原函数不会在内存中释放。 展开
展开全部
C语言函数调用整个过程是当准备调用函数时,先将形参以从右往左进行压栈程序跳转到函数入口,将函数的局和烂部变量压栈(如果函数内部再调用函数就是在重复这个过程),函销则数返回时出栈,递归是在最后一个点上面函数返回,前面分配的资源根本没有释放,递归只有在最后一个返回点上面,根据递归顺序反过来释放资源,亏棚棚这也是为什么当递归的数据量比较大或者递归的层次比较深的时候,很容易造成内存溢出的原因
追问
那函数递归调用是在内存中进行还是在CPU中进行运算的?我一直觉得是在内存中,可楼上说了之后我就不确定了。
追答
内存一般分两种堆,栈,堆(像malloc分配的就是堆)是低位地址向高位地址进发,栈是从高位地址向低位地址进发,递归的运算(绝大部分的程序运算,少数除外)是在CPU的寄存器中对数据进行操作的!
展开全部
首先系统执行C语言程序是有个栈和堆的
递归过程主要用到了栈
栈的原理是先进先出孙伏,相当于摞盘子辩凯轿,我只能拿走最上面的那个
系统执行函数时会把函数压入栈里
递归的过程就是利用这点,把函数压入栈中,但是这个函数的结果需要执行另一个函数,再继续压入栈中,知道出携肆现递归出口,就是最后一个函数有了结果
开始回调,一个一个出栈,跟楼主的结论2差不多
递归过程主要用到了栈
栈的原理是先进先出孙伏,相当于摞盘子辩凯轿,我只能拿走最上面的那个
系统执行函数时会把函数压入栈里
递归的过程就是利用这点,把函数压入栈中,但是这个函数的结果需要执行另一个函数,再继续压入栈中,知道出携肆现递归出口,就是最后一个函数有了结果
开始回调,一个一个出栈,跟楼主的结论2差不多
追问
那递归调用的话一直在内存用开辟新空间,内存占用会不会很大。还有,要怎么样才能算出一个函数所占用的内存空间呢?
内存占用这个是我最关心的问题。
追答
递归调用会很慢比如说计算斐波那契数列时如果用递归计算第40几个就要用半分钟,而且系统栈是固定的,递归调用次数过多会造成栈溢出,并不是开辟空间,系统栈根据电脑不同大小也不同
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
函数其实没有释放内存的概念,因为函数都是在指令区,而不是通常迟空陵所说的释放内存对应的数据区,不过在整个程序执行完之后指令区也是要释放的。
函数调用的大概过程如下:
1,将调用函数的上下文入栈;
2,调用被调用函数;
3,被调换函数执行;
4,调用函数上下文出栈,继续执行后继指令。
所以在函数调用过程中原调用函数是不会退出的-----即你所说的释放内存。
具体到你给的代码:
首先main中调用test, 进入test后要求读入一个char, 你输入'1'后执行case '1'中语句,所以输出“已调用”,然后就执行test()语句,即递归调用,此时main调用的test要等新的test执行完毕才能继续执行后继的i++语句;
再次进入test之后与从main中进入时一样,如果输入的是'1'会接着递归调用test,由于你输入了5次1,所以会继码戚续调用5次test;
在最后一个test中你输入了ESC? 所以不再走case '1'而走default了,所以输出"222222"; switch执行完之后判断c==27满足,所以while循环退出,继续执行printf语句,由于之前的test统统没有执行过case 1里的i++语句,所以全局变量i还是0;输出i=0; 到此最后一次test执行完毕;
倒数第二次的test继续执行i++, 所以i=2了,case 1执行完毕,但由于没有写break语句,所以继续执行default 语句,输出"222222", 退出switch语句,判断c==27, 由于c是全局变量,且最后一次输入的刚好是ESC, 所以判断满足, 退出while循环,输出i=1, 到此亏宽倒数第二次test执行完毕;
与倒数第二次类似的继续执行倒数第三、倒数第四、倒数第五和最终的第一次test后继代码,也就输出如你列出的结果了。
函数调用的大概过程如下:
1,将调用函数的上下文入栈;
2,调用被调用函数;
3,被调换函数执行;
4,调用函数上下文出栈,继续执行后继指令。
所以在函数调用过程中原调用函数是不会退出的-----即你所说的释放内存。
具体到你给的代码:
首先main中调用test, 进入test后要求读入一个char, 你输入'1'后执行case '1'中语句,所以输出“已调用”,然后就执行test()语句,即递归调用,此时main调用的test要等新的test执行完毕才能继续执行后继的i++语句;
再次进入test之后与从main中进入时一样,如果输入的是'1'会接着递归调用test,由于你输入了5次1,所以会继码戚续调用5次test;
在最后一个test中你输入了ESC? 所以不再走case '1'而走default了,所以输出"222222"; switch执行完之后判断c==27满足,所以while循环退出,继续执行printf语句,由于之前的test统统没有执行过case 1里的i++语句,所以全局变量i还是0;输出i=0; 到此最后一次test执行完毕;
倒数第二次的test继续执行i++, 所以i=2了,case 1执行完毕,但由于没有写break语句,所以继续执行default 语句,输出"222222", 退出switch语句,判断c==27, 由于c是全局变量,且最后一次输入的刚好是ESC, 所以判断满足, 退出while循环,输出i=1, 到此亏宽倒数第二次test执行完毕;
与倒数第二次类似的继续执行倒数第三、倒数第四、倒数第五和最终的第一次test后继代码,也就输出如你列出的结果了。
更多追问追答
追问
也就是说,函数是在CPU中进行运算的,递归调用的话不会在内存用开辟新的空间,而是在CPU中开辟新空间?
追答
CPU是纯计算用的,里边只有寄存器和很少量的缓存,不管是不是递归调用都不会在CPU中开辟空间。 递归调用主要消耗内存的栈空间, 可以认为调用一次函数就要增加一次栈空间, 不递归调用的话只增加一次栈空间。
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询