(复杂)声明如何根据优先级和关联性进行解析?

时间:2014-07-10 19:56:27

标签: c++

表达式声明中使用了&*等符号,这是两个独特的概念。

表达式中,符号是运算符,我们有一个明确定义的优先级和关联性表。当表达式很复杂时,我们可以使用此表对其进行分解和分析。 例如

    (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]
也许是在()内阅读,但是有多个()?(我没见过一个但是有可能。)

2 个答案:

答案 0 :(得分:3)

您使用螺旋规则。

对它的一个很好的解释是here

答案 1 :(得分:2)

表达式没有优先表!

运算符的优先级是从语法中推断出来的。例如,考虑 logical-and-expression logical-or-expression 的定义:

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。必须将其解析为 logical-or-expression (其中左侧是 logical-or-expression a,右侧是逻辑和表达 b && c)。它不能被解析为逻辑和表达式,因为如果它是,那么左侧a || b必须是逻辑 - 和-expression 也是如此。

另一方面,在(a || b) && c中,您无法将其解析为逻辑或表达式,因为您已经(a作为左侧,b) && c作为右侧,两者都不是有效的表达式。您可以将其解析为逻辑和表达式,因为与(a || b)不同,a || b是有效的逻辑和表达式

编译器解析代码,并构建语法树。如果根节点是 logical-or-expression ,则逻辑OR操作最后完成。如果根节点是逻辑和表达式,则逻辑AND操作最后完成。等等。

好的,这是坏消息。现在是好消息。

即使表达式中的运算符没有优先级表,但大多数情况下你可以假装它(当然它可以用括号覆盖);这就是你如何在心理上解析表达方式。因此,事实证明,声明者也是如此。没有优先级表,但您可以在精神上解析它们,就好像有。

事实上,C的设计者有足够的智慧使声明使用相同的"优先规则"作为表达。这是"声明遵循用法"规则。例如,在表达式

(*a)[10]

我们有一个包含间接表达式的数组索引表达式,而不是反之亦然。以同样的方式,在

int (*a)[10];

我们有一个包含指针声明符的数组声明符,而不是反之亦然。 (因此,结果是指向数组的指针。)因此,如果您记住表达式[](数组索引)和()(函数调用)的优先级高于*(间接) ,您也可以将相同的顺序应用于理解声明。 (引用是一种特殊情况;很容易记住,引用在声明中具有相同的"优先级"作为指针。)