C/C++编译器如何根据运算符的优先级和关联性分隔标记?

Mic*_* Lu 3 c c++ compiler-construction ternary-operator operator-precedence

请考虑以下代码:

int a = 3;
int b = 0;
b = a > 0 ? ++b, ++a : --a, b = 0;
Run Code Online (Sandbox Code Playgroud)

执行后,我得到的价值b,成为0与价值a,成为4.
这意味着条件表达式的结果a > 0被评估为true并且表达式a++已被执行,而执行b = 0后的表达式也被执行,.换句话说,表达式b = 0不是三元运算符的操作数,++b而是.否则,b = 0将不执行,因为条件表达式未被计算为false.

我的问题是"根据编译器b = 0从三元运算符的操作数中取出什么规则?"

第三个语句中的运算符包括:++--,具有最高优先级,>具有第二大优先级,? :并且=具有第三大优先级和,最低优先级.我知道,有较高的优先级运营商应确定自己的操作数前面,这样++,-->首先被处理.然后声明是等价的:

b = (a > 0) ? (++b), (++a) : (--a), b = 0;
Run Code Online (Sandbox Code Playgroud)

现在,它是=?:我们谈谈处理.的关联性=?:right-to-left的,所以我认为编译器会从右边end.The第一运营商遇到了被解析的语句=b = 0组合在一起.第二个遇到的运营商是,.由于它的优先级低于当前正在分析的运算符,我假设编译器将跳过它.然后编译器遇到了:,它是三元运算符的一部分,所以它一直在解析.(实际上我不知道编译器如何知道它:?:解析整个三元运算符之前的一部分)问题来了.编译器遇到的下一个操作符是,,但编译器还没有完成确定操作数?:然而.在,具有低优先级?:.理论上应该跳过它; 令人惊讶的是,在实际测试中,此时(++b)并且(++a)已经被,操作员连接起来并且两者都被认为是操作数?:.这让我感到困惑.为什么最后一个,被忽略并且不包含在操作数中,?:而前一个,语句保存在三元运算符的操作数中?

有人可以通过这个例子澄清优先级和相关性的概念吗?当我第一次看到这段代码时,我对执行结果感到很困惑.我原以为表达式b=0也是三元运算符操作数的一部分; 因此b = 0将仅如果被执行a > 0false.

提前致谢.

rod*_*igo 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
    ...
Run Code Online (Sandbox Code Playgroud)

等等...

我们的想法是每种类型的表达式都可以生成复合表达式或其他类型的低优先级表达式.您只能expression使用括号转到根目录.

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

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

额外解释:第一个表达式是logical-or-expression,如果仔细查看语法,您会看到它排除了赋值运算符,条件运算符和逗号运算符.

所以你的表达:

b = a > 0 ? ++b, ++a : --a, b = 0
Run Code Online (Sandbox Code Playgroud)

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

等等...