4
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。

4

3 回答 3

12

优先级与评估顺序不同。优先级只是确定哪些操作数和运算符属于一起。评估的确切顺序是未指定的,除了逻辑运算符,它们以严格的从左到右的顺序进行评估以启用短路。

所以因为&&具有更高的优先级,所以首先将变量分组如下:

(++x) || (++y && ++z)

然后,按照从左到右的顺序++x进行评估。鉴于这++x是真的,就知道整个表达式是真的。所以表达式求值是短路的。 (++y && ++z)永远不会被评估。因此 y 和 z 永远不会增加。

于 2013-08-02T02:07:04.947 回答
8

带有逻辑运算符&&||从左到右求值的表达式:

C99,第 6.5.14-4 节与按位运算|符不同,运算||符保证从左到右的求值;在计算第一个操作数之后有一个序列点。如果第一个操作数比较不等于0,则不计算第二个操作数。

由于x++不为零,因此表达式会短路对 右侧的所有内容的评估||,包括它们的副作用。这就是为什么 onlyx++被评估,所以x成为2。其余变量1应保持在 。

于 2013-08-02T02:04:39.413 回答
3

表达式中没有序列点:

z = ++x || ++y && ++z;

在 的预增量z和分配到之间z

因此,如果++z实际评估了 ,那会使您立即进入未定义的行为领域,并且任何事情都可能发生。在没有中间序列点的情况下,不允许您两次修改同一个对象。附件 C(来自 C99)列出了所有的序列点,这里的控制点遵循一个完整的表达式(整个计算和赋值)。

6.5 Expressions /2状态:

在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。此外,应仅读取先验值以确定要存储的值。

但是,给定您的初始值为x1,++z在这种特殊情况下,不会评估表达式的一部分。这并没有降低表达式本身的危险性,因为它会在起点为x == -1and的情况下调用 UB y != -1

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

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

因此,++x首先评估的是,因为它评估为非零,++y && ++z所以永远不会评估。x递增2z设置为该值的“真实”值,或者1y在 处保持不变1

于 2013-08-02T02:02:53.407 回答