3

考虑以下代码:

int a = 3;
int b = 0;
b = a > 0 ? ++b, ++a : --a, b = 0;

执行后,我得到bto become 的值和 to become的0值。 这意味着条件表达式的结果,被评估为并且表达式已被执行,而后面的表达式也已被执行。换句话说,表达式不是三元运算符的操作数,while是。否则,将不会执行,因为条件表达式未评估为.a4
a > 0truea++b = 0 ,b = 0++bb = 0false

我的问题是“编译器根据什么规则踢出b = 0三元运算符的操作数?”

第三条语句中的运算符包括:++--,具有最高优先级,>,具有第二大优先级,? :=,具有第三大优先级和,最低优先级。我知道优先级较高的运算符应该更早地确定它们的操作数,以便首先处理++,-->。那么语句等价地是:

b = (a > 0) ? (++b), (++a) : (--a), b = 0;

现在,=轮到?:处理了。=?:is的结合性right-to-left,所以我认为编译器会从右端解析语句。遇到的第一个运算符 is=和 sob = 0 组合在一起。第二个遇到的运算符是,。由于它的优先级低于当前正在分析的运算符,我假设编译器会跳过它。然后编译器遇到了:,它是三元运算符的一部分,所以一直解析。(其实我不知道编译器在解析整个三元运算符之前怎么知道它:是一部分)问题来了。编译器遇到的下一个运算符是,但编译器尚未完成确定操作数的操作数?:,?:然而。的,优先级低于?:。理论上应该跳过;令人惊讶的是,在实际测试中,此时(++b)(++a)已经被运算符连接起来,,并且都被认为是 的操作数?:。这让我很困惑。为什么最后一个,被忽略并且不包含?:在前一个,in 语句的操作数中,而保留在三元运算符的操作数中?

有人可以用这个例子澄清优先级和关联性的概念吗?第一次看到这段代码时,我对执行结果感到非常困惑。我原以为表达式b=0也是三元运算符操作数的一部分;因此b = 0只会在a > 0is时执行false

提前致谢。

4

2 回答 2

6

优先级和关联性是不同的概念,但从技术上讲,C 和 C++ 标准没有规定。相反,他们给出了语法规则来推断表达式的结构。

相关规则如下:

conditional-expression:
    logical-or-expression
    logical-or-expression ? expression : assignment-expression

expression:
    assignment-expression
    expression , assignment-expression

primary-expression:
    ( expression )

postfix-expression:
    primary-expression
    ...

等等...

这个想法是每种类型的表达式都可以生成一个复合表达式或另一种较低优先级的表达式。您只能expression使用括号向上到根。

考虑到这一点,请注意在三个子表达式的每一个中conditional-expression,使用 的?:实际具有不同类型的表达式。中间一个是expression所以它可以接受任何类型的表达,即使是,or =(这里没有歧义,因为结尾:)。

但请注意,最后一个是assignment-expression,即除了 with 之外的任何一种表达方式,。如果你想使用它,你必须用()创建一个primary-expression代替它。

额外说明:第一个表达式是logical-or-expression,如果您仔细查看语法,您会发现它不包括赋值运算符、条件运算符和逗号运算符。

所以你的表达:

b = a > 0 ? ++b, ++a : --a, b = 0

实际上是一个expression 逗号 assignment-expression,其中第一个expressionb = a > 0 ? ++b, ++a : --a,第二个assignment-expressionb = 0

等等...

于 2013-10-30T13:56:39.033 回答
0

您的表达式被评估为(b = ((a > 0) ? (++b, ++a) : (--a))), (b = 0);

正如你所说的?:比逗号运算符具有更高的优先级,所以 b=0 不属于三元条件。三元运算符左右部分的区别在于,在左侧,编译器尝试将完整的字符串++b, ++a作为表达式求值(知道和之间的部分?必须:是表达式,而在右侧,编译器尝试尽可能地解析表达式。运算符的优先级表示编译器必须停在,. 在左侧,编译器不会停在 the 上,,因为这是表达式的合法部分。

于 2013-10-30T13:47:30.670 回答