C/C++编译器如何根据运算符的优先级和关联性分隔标记?
作者:互联网
请考虑以下代码:
int a = 3;
int b = 0;
b = a > 0 ? ++b, ++a : --a, b = 0;
执行后,我得到b的值变为0,a的值变为4.
这意味着条件表达的结果,a> 1. 0被评估为真并且表达式a已被执行,而表达式b = 0之后,也被执行.换句话说,表达式b = 0不是三元运算符的操作数,而b是.否则,将不执行b = 0,因为条件表达式未被评估为false.
我的问题是“根据什么规则编译器从三元运算符的操作数中踢出b = 0?”
第三个语句中的运算符包括:和 – ,具有最高优先级的>,它具有第二大优先级,? :和=,具有第三大优先级,并且具有最低优先级.我知道具有更高优先级的运算符应该更早地确定它们的操作数,以便 – ,和>先处理然后声明是等价的:
b = (a > 0) ? (++b), (++a) : (--a), b = 0;
现在,它是=和?:轮到你处理了. =和?的关联性是从右到左,所以我认为编译器将从右端解析语句.第一个运算符遇到= =所以b = 0被组合在一起.第二个遇到的操作符是,.由于它的优先级低于当前正在分析的运算符,我假设编译器将跳过它.然后编译器遇到:,它是三元运算符的一部分,所以它一直在解析.(实际上我不知道编译器如何知道:在解析整个三元运算符之前是?的一部分)问题来了.编译器遇到的下一个操作符是,但编译器还没有完成确定?:的操作数. ,优先级低于?:.理论上应该跳过它;令人惊讶的是,在实际测试中,(b)和(a)在此时由运算符连接,并且两者都被认为是?的操作数.这让我感到困惑.为什么最后一个被忽略并且不包含在?的操作数中:而前一个,in语句保存在三元运算符的操作数中?
有人可以通过这个例子澄清优先级和相关性的概念吗?当我第一次看到这段代码时,我对执行结果感到很困惑.我原以为表达式b = 0也是三元运算符的操作数的一部分;因此,只有当>执行时才会执行b = 0. 0是假的.
提前致谢.
解决方法:
优先级和关联性是不同的概念,但从技术上讲,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
...
等等…
我们的想法是每种类型的表达式都可以生成复合表达式或其他类型的低优先级表达式.您只能使用括号进入根表达式.
考虑到这一点,请注意使用?:的条件表达式实际上在三个子表达式中的每一个中都有不同类型的表达式.中间的一个是表达式,因此它将接受任何类型的表达式,即使使用,或=(由于结尾:)这里没有歧义.
但请注意,最后一个是赋值表达式,即除了带有的表达式之外的任何表达式.如果要使用它,则必须使用()创建一个primary-expression来将其括起来.
额外解释:第一个表达式是逻辑或表达式,如果仔细查看语法,您会看到它排除了赋值运算符,条件运算符和逗号运算符.
所以你的表达:
b = a > 0 ? ++b, ++a : --a, b = 0
实际上是一个表达式逗号赋值表达式,其中第一个表达式是b = a> 0? b,a: – a,第二个赋值表达式是b = 0.
等等…
标签:c-3,c,operator-precedence,ternary-operator,compiler-construction 来源: https://codeday.me/bug/20190825/1718710.html