$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;
}
,1
,0
。 0
的优先级应高于&&
。
为什么||
和b
仍然是c
?
答案 0 :(得分:13)
表达式++a || ++b && ++c
被分组为++a || (++b && ++c)
。 但是,仅当||
为++a
时,才评估0
的右侧。
答案 1 :(得分:12)
这里有三个问题:
优先顺序意味着++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
。但是,a
,b
和c
中的每一个都可以以任何顺序进行求值。必须先知道a * b
的结果,然后才能将其添加到c
的结果中,但这并不意味着{em> {em> {em {1}}。
第二,与C中的大多数运算符不同,a * b
和c
运算符强制执行从左到右的求值。像||
这样的表达式将被解析为&&
,但是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 ,因此可以保证其操作数的特定求值顺序为从左至右。
订购
......
- 如果在子表达式E1和E2之间存在一个序列点, 那么E1的值计算和副作用都是 E2的每次值计算和副作用之前先进行排序
规则
.....
2)在以下两个二进制运算符的第一个(左)操作数的求值之后和第二个(右)操作数的求值之前有一个序列点:&&(逻辑AND),|| (逻辑或)和,(逗号)。
逻辑或运算(expr1 || expr2)
采用short-circuiting行为。也就是说,如果expr2
是逻辑expr1
1
,则不会评估(true)
。
a
,b
和c
的初始值为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
。