x = y = z = 1;
z = ++x||++y&&++z;
运算符优先级如下 -
(pre-increment) > && > ||
所以答案应该是 -
1. 2||2 && 2
2. 2||1
3. 1
print x,y,z should be 2,2,1
但是,答案是2,1,1。
答案 0 :(得分:12)
优先顺序与评估顺序不同。优先级简单地确定哪些操作数和运算符属于一起。确切的评估顺序未指定除了与逻辑运算符,逻辑运算符按严格的从左到右的顺序进行评估以启用短路。
因为&&
具有更高的优先级,所以变量首先分组如下:
(++x) || (++y && ++z)
然后,按照从左到右的顺序,评估++x
。鉴于++x
为真,众所周知整个表达式都是正确的。所以表达评估是短路的。 (++y && ++z)
永远不会被评估。因此y和z永远不会增加。
答案 1 :(得分:8)
逻辑运算符&&
和||
的表达式从左到右进行评估:
C99,第6.5.14-4节与按位
|
运算符不同,||
运算符保证从左到右的评估;在评估第一个操作数后有一个序列点。如果第一个操作数与0
不相等,则不评估第二个操作数。
由于x++
不为零,因此表达式会对||
右侧的所有内容进行短路评估,包括其副作用。这就是仅评估x++
的原因,因此x
变为2
。其余变量保持在1
,正如他们应该的那样。
答案 2 :(得分:3)
表达式中没有序列点:
z = ++x || ++y && ++z;
在z
的预增量和z
的分配之间。
因此,如果实际评估++z
,则会立即进入未定义的行为区域,并且任何都可能发生。如果没有插入序列点,则不允许两次修改同一对象。附件C(来自C99)列出了所有序列点,这里的控制点是完整表达式(整个计算和赋值)。
6.5 Expressions /2
州:
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算修改一次。此外,先前的值应该是只读的,以确定要存储的值。
但是,假设您的初始值x
为1,则在此特定情况下不会计算表达式的++z
部分。这并不会使表达式本身变得不那么危险,因为它会在起点为x == -1
和y != -1
的情况下调用UB。
在这种情况下,标准的控制部分是6.5.14 Logical OR operator /4
:
与按位|不同运算符,|| operator 保证从左到右的评估; 在评估第一个操作数后有一个序列点。 如果第一个操作数与0不等,则不评估第二个操作数。
因此,首先评估++x
,因为它的计算结果为非零,所以++y && ++z
永远不会被评估。 x
增加到2
,z
设置为“真实”值,或1
,y
保持不变1