-1

我使用的书将逻辑运算符的关联性从右到左给出,所以我希望这段代码的结果是,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);

为什么是这样?

4

2 回答 2

6

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

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

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

于 2013-08-04T15:59:40.003 回答
2

这是一个微妙的话题。有两种订购方式;评估顺序和关联性。现在事实证明,对于&&||在 C 中,求值和关联性都是从左到右的,所以你的书是错误的。尽管这种情况下的关联性没有实际区别。

为了解释关联性,a || b || c如果||是从右到左的,则被视为a || (b || c)。但如果||是从左到右,则被视为(a || b) || c。好吧,两者在所有情况下都会产生相同的结果。所以布尔运算符的关联性并不重要(当然,对于其他一些运算符来说它确实很重要:(a - b) - c!= a - (b - c)

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

这意味着即使使用从右到左的评估,您也不会看到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)

于 2013-08-04T16:10:55.707 回答