C语言中逻辑运算符的优先级

时间:2018-07-06 15:02:53

标签: c

$1

根据gcc 8.1.0,输出为#include <stdio.h> int main(void) { int a = 0, b = 0, c = 0; ++a || ++b && ++c; printf("%d %d %d", a, b, c); return 0; } 100的优先级应高于&&

为什么||b仍然是c

6 个答案:

答案 0 :(得分:13)

表达式++a || ++b && ++c分组++a || (++b && ++c)但是,仅当||++a时,才评估0的右侧。

答案 1 :(得分:12)

这里有三个问题:

  1. 优先顺序。
  2. 评估顺序。
  3. 逻辑运算符的短路。

优先顺序意味着++a || ++b && ++c被评估为++a || (++b && ++c)

但是,由于逻辑运算符的短路要求,因此首先评估++a。只有将其评估为false时,才会评估(++b && ++c)。在您的情况下,++a的值为true。因此,(++b && ++c)从未被评估。

答案 2 :(得分:2)

逻辑OR运算符||(以及逻辑AND运算符&&)是执行短循环运算的少数运算符之一。

C standard的6.5.14节对逻辑OR运算符进行了以下说明:

  

4 与按位|运算符不同,||运算符保证   从左到右的评估;如果对第二个操作数求值,则存在   第一和第二次评估之间的顺序点   操作数。 如果第一个操作数比较不等于0,则第二个   操作数未评估。

因为++a的值为1,所以保证||运算符的结果为1,并且不对右侧进行求值。另外,由于&&的优先级高于||,因此||运算符的右侧为++b && ++c,这意味着++b++c都没有被评估。

答案 3 :(得分:1)

优先级仅控制表达式的解析方式,而不控制表达式的计算方式。算术*的优先级高于+,因此a * b + c被解析为(a * b) + c。但是,abc中的每一个都可以以任何顺序进行求值。必须先知道a * b的结果,然后才能将其添加到c的结果中,但这并不意味着{em> {em> {em {1}}。

第二,与C中的大多数运算符不同,a * bc运算符强制执行从左到右的求值。像||这样的表达式将被解析为&&,但是a || b && c总是先被评估 ,并且a || (b && c)仅在结果得到评估时a中的值为0。

答案 4 :(得分:0)

就优先级而言,x || y && z的行为就像x + y * z:第二个运算符的绑定比第一个更紧密,并且这些表达式等效于x || (y && z)和{{1} }。

问题中的x + (y * z)b没有增加的原因是,除了优先级之外,逻辑运算还会短路:一旦您足够了解结果,表达式的其余部分将被跳过。 c||都从左到右评估其参数,因此在&&a() || b()中,对a() && b()的调用发生在对{ {1}}。

在简单情况下,如果a()返回b(),则在表达式a()中将不会执行对true的调用,因为这不会影响结果。同样,如果a() || b()返回b(),则在表达式a()中,将不会执行对false的调用。

在示例代码中,将不执行对a() && b()b()的递增,因为b产生一个非零值,因此表达式的结果为c,而无需评估++a之后的任何内容。

答案 5 :(得分:-1)

运算符优先级与求值顺序无关。优先级是将不同类型的运算符及其操作数进行分组的优先级。

因此,表达式

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

将被评估为

++a || (++b && ++c);

逻辑AND和逻辑OR运算符构成 sequence points ,因此可以保证其操作数的特定求值顺序为从左至右

Order of evaluation

  

订购
  ......

     
      
  • 如果在子表达式E1和E2之间存在一个序列点,   那么E1的值计算和副作用都是   E2的每次值计算和副作用之前先进行排序
  •   
     

规则
  .....
  2)在以下两个二进制运算符的第一个(左)操作数的求值之后和第二个(右)操作数的求值之前有一个序列点:&&(逻辑AND),|| (逻辑或)和,(逗号)。

逻辑或运算(expr1 || expr2)采用short-circuiting行为。也就是说,如果expr2是逻辑expr1 1,则不会评估(true)

abc的初始值为0。在表达式中:

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

++a->预增量a
也就是说,表达式++a的值是a的增量值,即1。由于||运算符具有短路行为,因此不会评估||的右侧表达式。因此,您将获得输出-1 0 0


为了更好地理解,只需尝试更改表达式中的++a-> a++
后递增运算符也将操作数的值增加1,但表达式的值是递增操作之前操作数的原始值。因此,a++将被评估为0,并且由于短路行为,||运算符(++b && ++c)的右侧表达式将被评估。

逻辑与运算(expr1 && expr2)也采用短路行为。如果发生逻辑短路,则只有当第一个操作数expr2不能完全确定结果时,才评估第二个操作数expr1。也就是说,只有在expr2是逻辑expr1 1并且(true)会得到++b的情况下,1才会被求值。所以,如果你这样做

a++ || ++b && ++c;
^^^

输出为-1 1 1

相关问题