C++中条件运算符中逗号运算符的优先级是什么?

10

这里发生了什么?

#include <iostream>
using namespace std;

int main(){

    int x=0,y=0;
    true? ++x, ++y : --x, --y; 
    cout << "x: " << x << endl;
    cout << "y: " << y << endl; //why does y=0 here?

    x=0,y=0;
    false ? ++x, ++y : --x, --y; 
    cout << "x: " << x << endl;
    cout << "y: " << y << endl;
}

x: 1
y: 0

x: -1
y: -1
第二种情况看起来没问题。在第一种情况下,我希望x和y都增加到1,但只有左操作数增加了。

1
@AdrianCornish 这段代码可以编译通过;你试过了吗? - chrisaycock
2
@chrisaycock 实际上并不需要。如果你添加 #include <iostream>using std::cout; using std::endl; 也许会需要。 - obataku
2
是的。 OP 应该阅读 sscce.org,但就清晰度和细节而言,这已经高于平均水平了。 - David Grayson
3
在一个使用cout的代码问题中,#include <iostream>using namespace std;只是噪音。如果这些都是缺少的,并且读者无法弄清如何使其编译,那么他们没有回答C++问题的业务能力。 - Benjamin Lindley
相同的问题在《C++ Primer》第五版的第4.33题(习题)中也被提出了。 - Jaege
显示剩余3条评论
3个回答

20
第一个和以下代码等效:
(true  ? (++x, ++y) : (--x)), --y; 
第二个等同于:
(false ? (++x, ++y) : (--x)), --y; 
因此--y总是会被执行。在第一行中,增量先被执行,因此预期x = 1, y = 0。在第二行中,x的减量先被执行,因此预期x = -1, y = -1
Barmar在评论中指出:

如果有人想知道为什么++x++y之间的逗号没有相同的效果,那是因为(true? ++x)根本不是有效的。 因此编译器会继续扫描直到找到:,但在那之后它会停止,直到达到一个优先级较低的运算符[(在这个例子中是,)或者语句的结尾]


1
为了更准确地表达您的最后一段:运算符的优先级(和结合性)只影响运算符左右两侧操作数的绑定,而不影响中间的操作数。当然,三元运算符是唯一一个在第一位就有中间操作数的运算符。但沿着这个思路,我们可以将一对括号看作是一个一元(恒等)运算符,其单个操作数位于中间(在“运算符符号”之间),这解释了为什么它所实现的分组不受任何优先级规则的影响。 - Marc van Leeuwen

4
y的值为零,因为逗号在所有C++运算符中优先级最低。由于它的优先级低于三元条件运算符,条件运算符被解析为true? ++x, ++y : --xfalse? ++x, ++y : --x>。在这两种情况下,--y语句都会被无条件执行。

编辑第一个逗号不同,因为编译器发现了一个?,所以现在需要一个:来完成条件表达式的“真”部分。这就是为什么++x++y都被包括在内的原因。


4
如果有人想知道为什么++x++y之间的逗号没有相同的效果,那是因为(true?++x)根本无效。所以它会继续扫描直到找到:,但超出此范围后,它会在遇到优先级较低的运算符时停止扫描。 - Barmar
1
哦,永远不要写成 if(x==100,000) ,我曾经吃过苦头。;-) - Adrian Cornish

0

阅读标准

§5.18 Comma operator [expr.comma]

¶1 The comma operator groups left-to-right.

expression:
assignment-expression
expression , assignment-expression

A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discardedvalue expression (Clause 5).83 Every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression. The type and value of the result are the type and value of the right operand; the result is of the same value category as its right operand, and is a bit-field if its right operand is a glvalue and a bit-field.

¶2 In contexts where comma is given a special meaning, [ Example: in lists of arguments to functions (5.2.2) and lists of initializers (8.5) —end example ] the comma operator as described in Clause 5 can appear only in parentheses. [ Example:

f(a, (t=3, t+2), c);

has three arguments, the second of which has the value 5. —end example ]


感谢。true? (++x,++y) : (--x,--y); 问题已解决。教训:在意图复杂的情况下始终使用括号。 - hhbilly
2
@user1626720 - 更不用说“不要滥用三元运算符”了。涉及到的代码应该使用if ... else来编写,因为三元运算符的值会被丢弃。 - Pete Becker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接