在回报声明中评估 [英] Evaluation in return statement

查看:152
本文介绍了在回报声明中评估的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  // prog1.c 
#include< stdio.h>
int f(int * a,int * b,int c){
if(c == 0)return 1;
else {
* a = * a + 1;
* b = * b - 1;
c = c - 1;
return(* a + f(a,b,c)+ * b);


int main(){
int a = 3,b = 3,c = 3;
printf(%d \ n,f(& a,& b,c));
返回0;
}

我使用 gcc clang-3.5 并找到输出 = 16



我认为可能会有一些实现特定的行为,如下面的代码:

  // prog2.c 
#include< stdio.h>
int f(int * x,int * y,int * z){
* x = * x + 1;
* y = * y + 1;
* z = * z + 1;
返回0;
}
int main(){
int a = 0,b = 0,c = 0;
printf(%d%d%d \ n,a,f(& a,& b,& c),b);;
返回0;
}
// gcc输出:1 0 0
// clang-3.5:0 0 1


$ b $ prog1.c 是否存在 return 语句中的任何实现特定行为?如果不是评估的方式如何?



我可能不知道某种未定义的行为或者,未指定的行为。请解释。
Thanks

解决方案

正如评论和近乎重复的问题(这是C中的未定义行为吗?如果不是这样,则预测逻辑输出。),这两个程序的结果都没有完全由C标准定义 - 它们会产生'未指定的行为',因为在第一个和第三个 printf()调用的返回语句中,第二个不是由语言指定的,而是编译器的心血结晶。 (请注意,这是'未指定的行为',而不是正式的'未定义行为' - 请参阅注释中的讨论,它不是'实现定义'行为;实现并不需要记录它的作用。)



这意味着任何实现给出的结果都是问题条款中的特定实现。不同的实现可能会合法地产生不同的答案。

第一个程序是:

  #include< stdio.h> 
$ b $ int f(int * a,int * b,int c){
if(c == 0)return 1;
else {
* a = * a + 1;
* b = * b - 1;
c = c - 1;
return(* a + f(a,b,c)+ * b);



int main(){
int a = 3,b = 3,c = 3;
printf(%d \ n,f(& a,& b,c));
返回0;

$ / code>

有问题的部分是 return(* a + f (a,b,c)+ * b);因为可以在递归函数调用之前或之后计算 * a ,并且 f()修改了 a b 点的值,所以评估事宜的顺序。不同的编译器可以合法地产生不同的结果。相同的编译器可以在不同的时间,或不同的优化标志下或按照它的选择产生不同的结果。可以在调用之前或者在调用之后或者可以评估任何一个之前评估 * a * b 第二个程序是:

$ $ p

pre> #include< stdio.h>
int f(int * x,int * y,int * z){
* x = * x + 1;
* y = * y + 1;
* z = * z + 1;
返回0;
}
int main(){
int a = 0,b = 0,c = 0;
printf(%d%d%d \ n,a,f(& a,& b,& c),b);;
返回0;

$ / code>

问题在于 a f(& a,& b,& c) b 是对 printf()的调用进行评估并不是由标准指定的,并且根据编译器选择的顺序得到不同的结果。您显示GCC和Clang会产生不同的结果 - 根据标准,这些结果都是可以接受的,所以还有很多其他结果。


//prog1.c    
#include <stdio.h>
    int f(int *a,int *b,int c) {
      if(c == 0) return 1;
      else {
        *a = *a + 1;
        *b = *b - 1;
         c =  c - 1;
         return (*a + f(a,b,c) + *b);
      }
    }
    int main() {
      int a = 3,b = 3,c = 3;
      printf("%d\n",f(&a,&b,c));
      return 0;
    }

I executed the program using gcc and clang-3.5 and found output = 16.

I think there might be some implementation specific behaviour like the follwoing code

//prog2.c
#include <stdio.h>
int f(int *x,int *y,int *z) {
  *x = *x + 1;
  *y = *y + 1;
  *z = *z + 1;
  return 0;
}
int main() {
  int a=0,b=0,c=0;
  printf("%d %d %d\n",a,f(&a,&b,&c),b);;
  return 0;
}
// gcc output : 1 0 0
// clang-3.5 :  0 0 1

In prog1.c is there any implementation specific behaviour in the return statement ? If not how is it evaluating ?

I may not know some kind of undefined behaviour Or, unspecified behaviour. Please explain. Thanks

解决方案

As noted in comments and in the near duplicate question (Is this undefined behaviour in C? If not, predict the output logically.), the results from both these programs are not fully defined by the C standard — they produce 'unspecified behaviour' because the order of evaluation of the terms in the return statement of the first and the printf() call in the second is not specified by the language and is at the whim of the compiler. (Note that it is 'unspecified behaviour' rather than formally 'undefined behaviour' — see the discussion in the comments. It is not 'implementation defined' behaviour either; the implementation is not required to document what it does.)

That means that the results given by any implementation are 'implementation specific' in the terms of the question. Different implementations may legitimately produce different answers.

The first program is:

#include <stdio.h>

int f(int *a,int *b,int c) {
  if(c == 0) return 1;
  else {
    *a = *a + 1;
    *b = *b - 1;
     c =  c - 1;
     return (*a + f(a,b,c) + *b);
  }
}

int main() {
  int a = 3,b = 3,c = 3;
  printf("%d\n",f(&a,&b,c));
  return 0;
}

The problematic part is return (*a + f(a,b,c) + *b); because *a could be evaluated before or after the recursive function call, and f() modifies the values that a and b point at so the order of evaluation matters. Different compilers could legitimately produce different results. The same compiler could produce different results at different times, or under different optimization flags, or as it chooses. Both *a and *b could be evaluated before the call, or after the call, or either one could be evaluated before and the other after — and that just names 4 plausible alternatives.

The second program is:

#include <stdio.h>
int f(int *x,int *y,int *z) {
  *x = *x + 1;
  *y = *y + 1;
  *z = *z + 1;
  return 0;
}
int main() {
  int a=0,b=0,c=0;
  printf("%d %d %d\n",a,f(&a,&b,&c),b);;
  return 0;
}

The problem is that the sequence in which a, f(&a, &b, &c) and b are evaluated for the call to printf() is not specified by the standard and you get different results depending on the sequence chosen by the compiler. You showed that GCC and Clang produce different results — both those results are acceptable according to the standard, and so are plenty of others.

这篇关于在回报声明中评估的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆