需要呼叫和标准C输出?

时间:2016-07-27 17:34:11

标签: c programming-languages code-analysis semantics

以下代码在此处保留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在编程语言课程中解决的一个例子,任何想法   为我描述一下?感谢

3 个答案:

答案 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); 

有未定义的行为,因为

  • ++ii++都有副作用,即将i的值递增1。
  • printf中的逗号只是一个分隔符而不是[ sequence point ]
  • 即使函数调用本身是一个序列点,由于上述原因,未定义i的两次修改的顺序。

在你的情况下

func(func(1,1),func(0,0))

但是,外部funcfunc(1,1)func(0,0)的论据与上述情况相反,彼此无关。这些参数的任何评估顺序最终都会导致无限递归,因此程序因内存耗尽而崩溃。

答案 2 :(得分:0)

对于C,一般来说,没有使用类似a

的函数定义参数bint 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 != 0else return func(a,b);的分析会导致无限递归,因此这个结论并不确定。这样的代码可能具有有用的期望副作用(例如,堆栈溢出和系统重置。)因此分析可能需要保守,并且假设func(1,1)永远 return和 not 优化了通话,即使它优化了func(0,0)通话。