复杂声明在优先级和结合性方面如何解析?

3
符号,比如&*等,在表达式和声明中都有使用,这是两个不同的概念。
在表达式中,这些符号是运算符,我们有一个明确定义的优先级和结合性表。当表达式很复杂时,我们可以使用这个表来分解和分析它。例如:
    (a + b) * ++c
问题: 在 声明 中,这些符号不是 运算符,因此我们不能应用 运算符优先级和结合律表是否存在适用于声明中符号的优先级和结合律表? 换句话说,当一个声明变得复杂时(尝试这个 int*& (*&f(int*))),是否有一种系统化的方法来分解和分析它?

一个密切相关的后续问题: 有些书籍(入门指南)教我们如何阅读复杂的声明,例如使用 typedef 的示例:

typedef int (*tp_alias)[10]; //defines tp_alias as an pointer to an array of 10 int

书上教授的方法是:以别名作为阅读的起点tp_alias 是新类型名称。向左看,它有一个 *,所以它是一个指针。然后看括号外部:向右,[10] 表示它是一个大小为 10 的数组;向左,int 表示数组元素为 int。
跟进问题: 我们如何阅读其他类型的别名声明,例如使用 using 声明的别名?由于别名不再处于位置,该怎么办?例如: using tp_alias = int (*)[10]
也许可以从 () 内部开始阅读,但如果有多个 () 怎么办?(我没有见过,但这是可能的。)


相关: https://dev59.com/1WYr5IYBdhLWcg3wRoOW - jrok
2个回答

3
您使用螺旋法则。

这个方法的一个好的解释可以在这里找到。


2

表达式没有优先级表!

运算符的优先级是从语法中推导出来的。例如,考虑逻辑与表达式逻辑或表达式的定义:

logical-and-expression:
    inclusive-or-expression
    logical-and-expression && inclusive-or-expression

logical-or-expression:
    logical-and-expression
    logical-or-expression || logical-and-expression

现在考虑表达式a || b && c。它必须被解析为一个逻辑或表达式(其中左侧是逻辑或表达式a,右侧是逻辑与表达式b&&c)。它不能被解析为逻辑与表达式,因为如果是这样,那么左侧的a || b也必须是逻辑与表达式,而它不是。
另一方面,在(a || b) && c中,你不能将其解析为逻辑或表达式,因为这样你就会得到(a作为左侧和 b)&& c 作为右侧,而且两者都不是有效的表达式。你可以将其解析为逻辑与表达式,因为(a || b),与 a||b 不同,是一个有效的逻辑与表达式。
编译器解析代码并构建语法树。如果根节点是逻辑或表达式,则最后执行逻辑或操作。如果根节点是逻辑与表达式,则最后执行逻辑与操作,以此类推。
好消息是,尽管表达式中没有运算符优先级表,但大多数情况下你可以假装有一个(当然可以通过括号覆盖),这就是你心理上解析表达式的方法。因此,事实证明声明也是如此。虽然没有运算符优先级表,但你可以在头脑中按照相同的“优先规则”来解析它们。这就是“使用先于声明”的规则。例如,在表达式中:
(*a)[10]

我们有一个包含间接表达式而不是反之的数组索引表达式。同样地,在IT技术中,这非常重要。

int (*a)[10];

我们所拥有的是一个包含指针声明符的数组声明符,而不是反过来。因此,结果是一个指向数组的指针。因此,如果您还记得表达式中[](数组索引)和()(函数调用)的优先级高于*(间接运算符),那么您可以将这种顺序应用于理解声明。 (引用是一种特殊情况;很容易记住,在声明中,引用与指针具有相同的“优先级”)。

非常详细的解释。但我很难相信运算符没有优先级。我刚查了cppreference(见下面链接)和C ++ Primer(第5版,第166页)。两者都说运算符有良好定义的优先级。[链接:http://en.cppreference.com/w/cpp/language/operator_precedence] - user3424826
你的意思是说子表达式没有求值顺序吗?例如f()+g()+h();不指定哪个函数先求值?我同意这一点。 - user3424826
@user3424826 那个表格不符合标准。在标准中没有优先级,只有规则来确定哪些类型的表达式可以包含哪些其他类型的表达式。这确实有所区别。考虑表达式 w ? x , y : z。如果编译器基于“优先级”进行解析,则该表达式将无法形成,因为它将被解析为 (w ? x) , (y : z) - Brian Bi
我试图查阅C++标准,但没有找到相应的表格。但仍有两个需要解释的问题:1. 在声明和表达式中,这些符号是否具有相同的优先级指示?(请引用标准)2. 在类型别名中是否可能有多个括号?例如,像using tp_alias = int (*)(*)这样的(合法)代码(我知道这个不合法),是否会让解析器产生困惑? - user3424826
@modeller 我不相信标准规定了优先级是一样的,但你可以自己推断出它们的优先级,而且众所周知它们是相同的。至于多个括号,例如 int ((*a))[10],也算吗?你可以在任何有意义的位置使用括号。 - Brian Bi
显示剩余2条评论

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