如何确定逻辑表达式中函数调用的顺序

时间:2019-04-08 12:39:27

标签: c

我对函数调用的顺序感到困惑。我已经列出了我尝试过的命令,但答案仍然错误。

!!!答案是“ i和j值未定义。”

根据运算符优先级:

  
      
  1. 如果编译器从左到右计算值
  2.   
   int i = (1+0) || (ignored);  //1  
   int j = (1) || (ignored);   //1 
  
      
  1. 如果编译器首先计算'+'之后的值,则从左到右计算其他值
  2.   
   int i = (0+0) || (1);  //1  
   int j = (2) || (ignored);   //1 

我仍然得出错误的结论。

所以我尝试违抗运算符优先级

  
      
  1. 如果编译器首先计算从右到左的值
  2.   
   int i = (1+1) || (0);  //1
   int j = (ignored) || (2+2);  //1
  
      
  1. 如果编译器仅首先计算'+'之前的值,则从右向左计算其他值
  2.   
   int i = (0+1) || (0);  //1  
   int j = (ignored) || (1+2);    //1

我仍然得出错误的结论。

我再次猜测,编译器可能不会忽略||之后的表达式。即使左为真

  
      
  1. 如果编译器从左到右计算值
  2.   
   int i = (1+0) || (1);    //1
   int j = (2) || (2+3);    //1
  
      
  1. 如果编译器首先计算'+'之后的值,则从左到右计算其他值
  2.   
   int i = (0+0) || (1);    //1
   int j = (2) || (3+3);    //1
  
      
  1. 如果编译器首先计算从右到左的值
  2.   
   int i = (1+1) || (0);  //1
   int j = (3) || (2+2);  //1
  
      
  1. 如果编译器仅首先计算'+'之前的值,则从右向左计算其他值
  2.   
   int i = (0+1) || (0);  //1
   int j = (3) || (1+2);  //1

我仍然得出错误的结论。

#include<stdio.h>
int x = 0;
int f(){
  if(x == 0) return x + 1;
  else return x - 1;
}
int g(){
  return x++;
}
int main(){
  int i = (f() + g()) || g();
  int j = g() || (f() + g());
}

无论顺序如何,除了i = 1且j值为1之外,我都是
。 但是答案是i和j值未定义。
我不知道哪种情况会导致其他输出...
原谅我的愚蠢.......

3 个答案:

答案 0 :(得分:3)

Let's analyse i. Note that the second argument of || is only evaluated if the left hand argument is 0.

i is always 1 even if the approach by which this result is attained is unspecified.

There's no undefined behaviour here. (Formally this is due to the fact that a function call is a sequenced step.)

The language does not specify the order in which f() and g() are called in the evaluation of the left hand side. That is left to the implementation. Formally it is not even implementation defined since an implementation is not required to document the behaviour. If f() is called first then the value of f() + g() is non-zero. If g() is called first then f() + g() is zero, so g() is called again, and that is also non-zero as x is 1 at that point.

j drops out trivially as 1 since only the left hand side of || is evaluated.

A more interesting variant would be

int f(){
  if(x == 0) return ++x;
  else return --x;
}

where actually different implementations could return 0 or 1 for i or j.

答案 1 :(得分:2)

I'm going to go out on a limb and claim that the exam's answer is wrong.

Starting with the first expression to be evaluated,

f() + g()

The ordering of the function calls is unspecified but they can't be interleaved, so there are two cases;

  1. f(), then g()
    f() returns 0 + 1 which is 1, then g() returns the value of x, which is 0, and increments x. The result is 1, which gets converted to true.

  2. g(), then f()
    g() returns 0 and increments x, then f() returns x - 1 (because x is 1 now), which is 0.
    This result is 0, which is false.

x is incremented to 1 in both cases.

In case 1, evaluation stops, i is 1, and x is 1.

In case 2, evaluation continues with g(), which returns 1 and increments x to 2.

Thus, regardless of the evaluation order, i is 1.
x, on the other hand, may be either 1 or 2.

For j, you have g() first, which returns either 1 or 2.

Since both 1 and 2 are truthy, j must be 1.

答案 2 :(得分:1)

Operator precedence and evaluation order are not the same thing.

For most operators, C makes no assumption in which order their arguments are evaluated. A compiler may even have different strategies during the same compilation, depending, e.g, on optimization opportunities.

The only operators that have a predefined ordering are those were there is a logical dependency from the left operannd to the right operand(s), e.g ||, &&, ?: and ,.

And if your are refering to the code at the end of your question, the answer is not "undefined" but "unspecified".