注意,由于表达式的定义是
表达式:
赋值表达式
表达式 , 赋值表达式
第二行表示任何assignment-expression都可以被认为是一个表达式,这就是为什么t=3, t+2是一个有效的表达式。
那么为什么语法是这样的呢?首先请注意,表达式的语法是从最紧密绑定的类别 primary-expression 到最不紧密绑定的类别 expression 逐步构建的。 (然后 "( expression )" 是一个 primary-expression 的事实使表达式语法完整循环,让我们使任何表达式更紧密通过添加括号来绑定而不是围绕它的所有内容。)
例如,众所周知的事实是二进制 * 比二进制 + 绑定更紧密,这源于以下语法片段:
乘法表达式:
pm-表达式
乘法表达式 * pm-表达式
乘法表达式 / pm-表达式
乘法表达式 % pm-表达式
加法表达式:
乘法表达式
加法表达式 + 乘法表达式
加法表达式 - 乘法表达式
在表达式2 + 3 * 4 中,文字2、3 和4 可以被认为是一个pm 表达式,因此也可以被认为是一个乘法表达式 或 additive-expression。所以你可能会说2 + 3 符合加法表达式的条件,但它不是乘法表达式,所以完整的@987654337 @ 不能那样工作。相反,语法强制3 * 4 被视为乘法表达式,因此2 + 3 * 4 可以是加法表达式。因此3 * 4 是二进制+ 的子表达式。
或者在表达式2 * 3 + 4 中,3 + 4 可能被认为是一个additive-expression,但它不是一个pm-expression,所以这不是'不工作。相反,解析器必须认识到2 * 3 是一个乘法表达式,它也是一个加法表达式,所以2 * 3 + 4 是一个有效的加法表达式,2 * 3 作为二进制 + 的子表达式。
当同一个运算符被使用两次或两个具有相同优先级的运算符被使用时,大多数语法定义的递归性质很重要。
回到逗号语法,如果我们有标记“a, b, c”,我们可能会说b, c 可能是一个表达式,但它不是一个赋值表达式,所以b, c 不能是整体的子表达式。相反,语法要求将a, b 识别为表达式,允许作为另一个逗号运算符的左子表达式,因此a, b, c 也是带有a, b 的表达式作为左操作数。
这对内置逗号没有任何区别,因为它的含义是关联的:“评估并丢弃a,则结果值来自评估(评估并丢弃b,然后是结果值来自评估c)”与“评估并丢弃(评估并丢弃a,则结果值来自评估b),然后结果值来自评估c”。
但它确实为我们提供了在operator, 重载的情况下明确定义的行为。给定:
struct X {};
X operator,(X, X);
X a, b, c;
X d = (a, b, c);
我们知道最后一行的意思
X d = operator,(operator,(a,b), c);
而不是
X d = operator,(a, operator,(b,c));
(我认为定义一个非关联的operator, 特别邪恶,但这是允许的。)