不明确的运算符优先级,请解释为什么运算符在这里没有遵循?

时间:2013-08-02 01:56:52

标签: c

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。

3 个答案:

答案 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 == -1y != -1的情况下调用UB。

在这种情况下,标准的控制部分是6.5.14 Logical OR operator /4

  

与按位|不同运算符,|| operator 保证从左到右的评估; 在评估第一个操作数后有一个序列点。 如果第一个操作数与0不等,则不评估第二个操作数。

因此,首先评估++x,因为它的计算结果为非零,所以++y && ++z永远不会被评估。 x增加到2z设置为“真实”值,或1y保持不变1