这个表达的结果是什么?

时间:2013-08-04 15:58:55

标签: c

我使用的书从右到左给出了逻辑运算符的关联性,因此我希望此代码的结果为2 2 1,但它是2 1 1

int x,y,z;
x=y=z=1;
z=++x||++y||++z;
printf("%d %d %d",x,y,z);

为什么会这样?

2 个答案:

答案 0 :(得分:6)

||有短路评估要求。如果第一个操作数与0不同,则不评估第二个操作数。

  

(C11,6.5.14逻辑OR运算符)p4“如果第一个操作数与0不等,则不计算第二个操作数。”

在您的情况下,++y++z永远不会被评估。

答案 1 :(得分:2)

这是一个微妙的话题。订购有两种类型;评估顺序和关联性。现在结果是,对于C中的&&||,评估和关联性都是从左到右,因此您的书是错误的。虽然这种情况下的关联性没有实际区别。

要解释关联性,a || b || c,如果||从右向左,则会被视为a || (b || c)。但如果||是从左到右,则会将其视为(a || b) || c。那么,在所有情况下都产生相同的结果。因此,布尔运算符的关联性并不重要(当然,它对其他一些运算符很重要:(a - b) - c!= a - (b - c)

评估顺序不同;它告诉我们在之后中比较事物的顺序,我们已经应用了关联性的隐式括号。因此,使用从左到右的评估顺序,a || (b || c)(和(a || b) || c)将按照a,然后b,然后c的顺序进行评估。从右到左,两者都将按cba的顺序进行评估。

这意味着即使是从右到左的评估,您也不会看到2 2 1,而是1 1 2。无论关联性如何。 (编辑:实际上你会看到1 1 1,因为你将z设置为表达式的结果,当然是true

另一个有趣的注意事项是,对于大多数运营商而言,评估订单实际上并未定义。这意味着(a ++) - (a ++)是未定义的行为(幸运的是,否则将是混淆的噩梦)

请参阅http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence

或更少的维基百科页面,http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm

此处还有第6条规则:http://en.cppreference.com/w/cpp/language/eval_order#Rules(我确定它符合标准,但我只能找到C ++ 03的引用,而不是C)