有关运算符优先级的示例

时间:2015-12-06 21:09:58

标签: c operator-precedence

据我所知,一元运算符优先于||&&。在下面的代码中,我期望输出所有输出都等于1.是的,存在短路,但不应该在||&&之前计算那些预增量?这些优先级如何在这里工作?

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int a = 0, b = 0, c = 0;
    a = b = c == 1;
    c = ++a || ++b && ++c;    // short-circuit here
    printf("a=%d, b=%d, c=%d\n", a, b, c);
}

Output:
a=1 b=0 c=1

3 个答案:

答案 0 :(得分:3)

运算符优先级评估顺序没有任何关系。更高的优先级意味着首先将操作数分组到该运算符。

声明

c = ++a || ++b && ++c;  

++的操作数的分组/绑定将首先进行,然后分别进行&&||的操作数的分组/绑定。为了表明这一点,我在表达式中添加了括号

  • ++具有更高的优先级,因此首先将操作数绑定到它

    c = (++a) || (++b) && (++c); 
    
  • &&的优先级高于||

    c = (++a) || ((++b) && (++c)); 
    
  • ||的优先级高于=

    c = ((++a) || ((++b) && (++c)));   
    
  • =所有

    的优先级最低
    (c = ((++a) || ((++b) && (++c))));   
    

答案 1 :(得分:2)

||短路且最低优先级运算符解释结果。由于++的优先级高于&&&&的优先级高于||,因此++a || ++b && ++c的表达式树为:

       ||   -- left:   ++a
            -- right:  &&   --left:  ++b
                            --right: ++c

因此,为了评估表达式,C首先考虑评估||的规则,由C11标准中的6.5.14给出。具体做法是:

  

6.5.14.4:与按位|不同运算符,||运营商保证从左到右的评估;如果计算第二个操作数,则在第一个和第二个操作数的计算之间存在一个序列点。如果第一个操作数将不等于0,则不计算第二个操作数。

||短路的事实意味着它首先评估其左操作数,并且只有在左边为零时才评估其右操作数。因此,要评估表达式++a || ++b && ++c,C需要以下内容:

  1. 评估++aa加1,表达式等于其递增值)。如果它不为零,则||表达式等于1 ,并且永远不会评估右侧。
  2. 否则,请按从左到右的顺序评估++b++c。如果++b为零,则永远不会评估++c。如果两者都不为零,则表达式等于1
  3. 由于++a的计算结果为1,因此永远不会评估||的右侧。这就是您a==1b==0c==1

    的原因

    语句c = ++a || ++b && ++c还有一个问题,即语句可能会调用未定义的行为。如果++a为false且++b为true,则必须对++c进行评估。但是,c = ...++c之间没有序列点。由于表达式都修改c而两者之间没有序列点,因此行为未定义。有关此内容的进一步说明,请参阅https://stackoverflow.com/a/3575375/1430833

答案 2 :(得分:1)

我认为您将operator precedenceorder of evaluation混为一谈。这里概述了发生的事情。在评论中,我对=的使用是身份的 - 就像数学等号一样。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    // all variables are assigned the value 0
    int a = 0, b = 0, c = 0;

    // a and b are equal to the evaluation of `c == 1`, which is false. a and b are 0
    a = b = c == 1;

    /* 
       && has higher precedence than ||, so ++b and ++c are "grouped": ++a || (++b && ++c)
       ++a is evaluated, a = 0+1 = 1. 1 is true, short circuit the second grouping. 
       c = a = 1.
    */
    c = ++a || ++b && ++c;    // short-circuit here

    // a = c = 1, b = 0
    printf("a=%d, b=%d, c=%d\n", a, b, c);
}