BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #25011同步于 2009/6/11
CPP机器人发帖

[合集] 这个程序会不会终止?为什么?

shenlei
2009/6/11镜像同步0 回复
☆─────────────────────────────────────☆ wks (cloverprince) 于 (Fri Mar 13 13:10:16 2009) 提到: #include<stdio.h> int f(int x, int y) { if(x==0) { return 0; } else { return f(x-1,f(y-2,x)); } } int main() { printf("%d\n",f(2,1)); return 0; } 按道理说, f(2,1) == f(1,f(1,2)) == f(0,f(f(-1,2)-2,1)) == 0 ☆─────────────────────────────────────☆ AFX (新手上路) 于 (Fri Mar 13 13:39:44 2009) 提到: 【 在 wks 的大作中提到: 】 : #include<stdio.h> : int f(int x, int y) { : if(x==0) { : ................... 应用序 和 正则序 你给出的是正则序,实际上C++应该是应用序? 即在f(1, f(-1,2))这一步,C++会先求值里面的f(-1,2),再求值外层的f。 所以应用序是“先求值参数而后应用”,请看SICP中文版第十页。顺便参考SICP第13页的练习1.5 ☆─────────────────────────────────────☆ ZMBird (Jack) 于 (Fri Mar 13 14:00:10 2009) 提到: 个人意见是这个程序在可以预见的未来+不可以预见的未来执行的话都会因为堆栈溢出而终止。 但考虑到不论f()的参数为什么,都会因为int 类型进行-1操作后会下越界,终有重新调用f(0,???)的时候,此时f()开始返回。可是每次调用f()等到能够返回函数的时候调用f()的次数期望在2^8*sizeof(int),而f()几乎每次又会重新调用f(),这种计算复杂度在宇宙毁灭的时候必定还没有执行完。 ☆─────────────────────────────────────☆ AFX (新手上路) 于 (Fri Mar 13 14:06:54 2009) 提到: 【 在 ZMBird 的大作中提到: 】 : 个人意见是这个程序在可以预见的未来+不可以预见的未来执行的话都会因为堆栈溢出而终止。 : 但考虑到不论f()的参数为什么,都会因为int 类型进行-1操作后会下越界,终有重新调用f(0,???)的时候,此时f()开始返回。可是每次调用f()等到能够返回函数的时候调用f()的次数期望在2^8*sizeof(int),而f()几乎每次又会重新调用f(),这种计算复杂度在宇宙毁灭的时候必定还没有执行完。 也不一定,如果采用应用序,但是如果编译器可以进行尾递归优化的话,就不会存在因为无限递归带来的堆栈溢出的问题,顶多死循环。 如果是编译器是按照正则序来求值的话,在第二步程序就终止了,就按照ws大牛列出的式子一样。 但是我所见到的C++编译器都是应用序求值,并且不带尾递归优化的 ☆─────────────────────────────────────☆ Vampire (吸血鬼) 于 (Fri Mar 13 14:34:22 2009) 提到: 从汇编代码看是先计算了 return f(x-1,f(y-2,x)); 里面的那个f(y-2,x) ………… ☆─────────────────────────────────────☆ TuBie (PesT是土鳖) 于 (Fri Mar 13 14:38:26 2009) 提到: 绕死我了,我大脑栈溢出了 ☆─────────────────────────────────────☆ nobody (nobody) 于 (Fri Mar 13 14:40:20 2009) 提到: 【 在 wks 的大作中提到: 】 : #include<stdio.h> : int f(int x, int y) { : if(x==0) { : ................... f(x-1,f(y-2,x)) f(2, 1) >> f(1, f(-1, 2)) 1>f(-1, 2)>>f(-2, f(0, -1))==f(-2, 0) 到f(-2, 0)这不函数就不会返回了 ☆─────────────────────────────────────☆ ZMBird (Jack) 于 (Fri Mar 13 15:00:06 2009) 提到: To nobody 可是int类型数据不停的-1会下越界啊,然后变成正数,再变成0. 你可以试试 int i=-1; while( i !=0 ) { i--; }; cout<<i<<endl; 这个不会是死循环。 调用f(x, y),不论怎样都会调用到 f( 0 ,???)的。 ☆─────────────────────────────────────☆ nobody (nobody) 于 (Fri Mar 13 15:12:15 2009) 提到: 【 在 ZMBird 的大作中提到: 】 : To nobody : 可是int类型数据不停的-1会下越界啊,然后变成正数,再变成0. : 你可以试试 : ................... int 越界之后完全是未定义行为,编译器又不给什么保障。 之后一切都没有可预见性 ☆─────────────────────────────────────☆ Jarod (学五608鬼魂) 于 (Fri Mar 13 16:49:35 2009) 提到: ....真无聊....不知有啥为什么的..... ☆─────────────────────────────────────☆ yihang (Goodluckfly) 于 (Fri Mar 13 17:08:51 2009) 提到: 【 在 nobody 的大作中提到: 】 : f(x-1,f(y-2,x)) : f(2, 1) >> f(1, f(-1, 2)) : 1>f(-1, 2)>>f(-2, f(0, -1))==f(-2, 0) : ................... 大脑栈溢出后,无聊的调试了一下 才发现就是这样,会导致函数一直压栈,栈资源耗光而退出 ☆─────────────────────────────────────☆ windam (棒棒糖) 于 (Fri Mar 13 21:45:31 2009) 提到: f(x-1,f(y-2,x)) 这个,C++编译器肯定会先对两个参数求值,然后才能把得结果压栈。。。 编译器应该还聪明不到把这种上下文把这种地方直接优化掉吧……
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。