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

C 如何确定逻辑表达式中函数调用的顺序,c,C,我对函数调用的顺序感到困惑。我已经列出了我试过的顺序,但仍然得到了错误的答案 !!!答案是“i和j值未定义。” 根据运算符优先级: 如果编译器从左到右计算值 如果编译器首先计算“+”之后的值,则从左到右计算其他值 我还是得出了错误的结论 所以我试着不服从操作符的优先级 如果编译器首先从右向左计算值 如果编译器仅首先计算“+”之前的值,则从右向左计算其他值 我还是得出了错误的结论 我再次猜测,编译器可能不会忽略| |之后的表达式,即使left为true 如果编译器从左到右计算值 如果编译器首先计算

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

!!!答案是“i和j值未定义。” 根据运算符优先级:
  • 如果编译器从左到右计算值
  • 如果编译器首先计算“+”之后的值,则从左到右计算其他值
  • 我还是得出了错误的结论

    所以我试着不服从操作符的优先级
  • 如果编译器首先从右向左计算值
  • 如果编译器仅首先计算“+”之前的值,则从右向左计算其他值
  • 我还是得出了错误的结论


    我再次猜测,编译器可能不会忽略| |之后的表达式,即使left为true
  • 如果编译器从左到右计算值
  • 如果编译器首先计算“+”之后的值,则从左到右计算其他值
  • 如果编译器首先从右向左计算值
  • 如果编译器仅首先计算“+”之前的值,则从右向左计算其他值
  • 我还是得出了错误的结论

    #包括
    int x=0;
    int f(){
    如果(x==0)返回x+1;
    否则返回x-1;
    }
    int g(){
    返回x++;
    }
    int main(){
    int i=(f()+g())| | g();
    int j=g()| |(f()+g());
    }
    
    无论顺序如何,除I=1和j值为1外,I为1。

    但答案是i和j值是未定义的。
    我想知道哪种情况会导致另一个输出…

    请原谅我的愚蠢……

    运算符优先级和求值顺序不是一回事

    对于大多数运算符,C不假设其参数的求值顺序。编译器在同一编译过程中甚至可能有不同的策略,这取决于优化机会等

    唯一具有预定义顺序的运算符是那些从左操作数到右操作数之间存在逻辑依赖关系的运算符,例如
    |
    &&
    ?:


    如果你在问题末尾提到了代码,答案不是“未定义”,而是“未指定”。

    让我们分析一下
    i
    。请注意,
    |
    的第二个参数仅在左侧参数为0时计算

    i
    始终为1,即使未指定获得此结果的方法

    这里没有未定义的行为。(从形式上讲,这是因为函数调用是一个顺序步骤。)

    该语言没有指定在计算左侧时调用
    f()
    g()
    的顺序。这就留给实现了。从形式上讲,它是而不是甚至是定义的实现,因为不需要实现来记录行为。如果先调用
    f()
    ,则
    f()+g()
    的值为非零。如果先调用
    g()
    ,则
    f()+g()
    为零,因此再次调用
    g()
    ,这也是非零的,因为此时
    x
    为1

    j
    由于只计算
    |
    的左侧,因此通常以1的形式退出

    一个更有趣的变体是

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

    实际上,不同的实现可能会为
    i
    j
    返回0或1,我将冒很大的风险,声称考试的答案是错误的

    从要计算的第一个表达式开始

    f() + g()
    
    函数调用的顺序未指定,但它们不能交错,因此有两种情况

  • f()
    ,然后
    g()

    f()
    返回
    0+1
    为1,然后
    g()
    返回
    x
    的值为0,并递增
    x
    。 结果为1,转换为
    true

  • g()
    ,然后
    f()

    g()
    返回0并递增
    x
    ,然后
    f()
    返回
    x-1
    (因为
    x
    现在是1),即0。
    此结果为0,即
    false

  • x
    在这两种情况下都增加到1

    在情况1中,求值停止,
    i
    为1,
    x
    为1

    在案例2中,求值继续执行
    g()
    ,它返回1并将
    x
    增加到2

    因此,无论评估顺序如何,
    i
    都是1。
    另一方面,
    x
    可以是1或2

    对于
    j
    ,首先是
    g()
    ,它返回1或2


    因为1和2都是真的,
    j
    必须是1。

    你可能想读一读“我已经考虑过了。是什么让你认为这些值是未定义的?”但答案是I和j值都是未定义的。“你从哪里得到这个答案的?”我再次猜测编译器可能不会忽略| |之后的表达式,即使left是真的。”不。在这种情况下,编译器必须忽略
    | |
    之后的部分。我讨论了许多情况,但发现无论求值顺序是什么,答案都是一样的:“I=1和j=1”。我已经运行了许多编译器的代码,每次使用printf(“%d,%d\n”,I,j),stdout都是“1,1\n”@Esual,这不是一个好的参数。唯一有帮助的是系统地写下所有可能的操作顺序。我第一次使用stackoverflow,所以我不能上传试卷的图片。这也是因为我不擅长c语法…实际上…你提到的情况是上面列出的案例1和案例2…如果先调用g(),那么f()+g()为零。As g()只调用一次。全局变量x变为1。因此,当再次调用g()时,g返回1。这意味着“inti=(0+0)| |(1);”@Esual:Oops你是对的。对答案做了一些小的修改,这很简单
       int i = (1+1) || (0);  //1
       int j = (ignored) || (2+2);  //1
    
       int i = (0+1) || (0);  //1  
       int j = (ignored) || (1+2);    //1
    
       int i = (1+0) || (1);    //1
       int j = (2) || (2+3);    //1
    
       int i = (0+0) || (1);    //1
       int j = (2) || (3+3);    //1
    
       int i = (1+1) || (0);  //1
       int j = (3) || (2+2);  //1
    
       int i = (0+1) || (0);  //1
       int j = (3) || (1+2);  //1
    
    int f(){
      if(x == 0) return ++x;
      else return --x;
    }
    
    f() + g()