以下代码在此处保留C语言语法:
#include <stdio.h>
int func(int a, int b){
if (b==0)
return 0;
else return func(a,b);
}
int main(){
printf("%d \n", func(func(1,1),func(0,0)));
return 0;
}
此代码的输出是什么,1)使用标准C,2)运行 通过need属性调用的语言,然后:
在(1)中程序循环进入无限通话,在(2)中我们有ouptut零!!这是TA在编程语言课程中解决的一个例子,任何想法 为我描述一下?感谢
答案 0 :(得分:3)
1)在C(使用strict evaluation semantics)中,我们得到无限递归,因为在严格评估中,在调用函数之前计算参数。因此,f(f(1,1), f(0,0))
f(1,1)
和f(0,0)
在外部f
之前进行评估(首先评估两个参数中的哪一个在C中未指定,但这无关紧要)。由于f(1,1)
导致无限递归,我们得到无限递归。
2)在使用non-strict evaluation的语言中(无论是按名称调用还是按需调用),参数被替换为未评估的函数体,仅在需要时进行评估。因此,对f
的外部调用首先进行评估:
if (f(0, 0) == 0)
return 0;
else return f(f(1,1), f(0,0));
因此,在评估if
时,我们需要评估f(0,0)
,它只是评估为0.所以我们进入if
的then-branch并且永远不执行其他 - 科。由于对f
的所有调用仅用于else分支,因此它们永远不需要,因此永远不会被评估。所以没有递归,无限或其他,我们得到0。
答案 1 :(得分:0)
要解决第一部分,
C草案,6.5.2.2-&gt; 10(函数调用)说
......实际参数的评估顺序是未指定的。
出于这样的原因,例如
printf("%d%d",i++,++i);
有未定义的行为,因为
++i
和i++
都有副作用,即将i的值递增1。 i
的两次修改的顺序。在你的情况下
func(func(1,1),func(0,0))
但是,外部func
即func(1,1)
或func(0,0)
的论据与上述情况相反,彼此无关。这些参数的任何评估顺序最终都会导致无限递归,因此程序因内存耗尽而崩溃。
答案 2 :(得分:0)
对于C,一般来说,没有使用类似a
b
和int func(int a, int b)
评估的顺序
显然评估func(1,1)
是有问题的,无论func(1,1)
是在func(0,0)
之前/之后/同时进行评估,代码都会受到影响
根据需要分析func(a,b)
可以得出结论:如果b==0
,则无需调用func()
然后替换为0。
printf("%d \n", func(func(1,1),func(0,0)));
// functionally then becomes
printf("%d \n", func(func(1,1),0));
再次申请
// functionally then becomes
printf("%d \n", 0);
当然,由于b != 0
和else return func(a,b);
的分析会导致无限递归,因此这个结论并不确定。这样的代码可能具有有用的期望副作用(例如,堆栈溢出和系统重置。)因此分析可能需要保守,并且不假设func(1,1)
将永远 return和 not 优化了通话,即使它优化了func(0,0)
通话。