编译器如何理解指针和数组的声明
How does compiler understand the declaration of pointers and arrays
当我对指向数组的指针和指针数组感到困惑时,我想到了这个问题,尽管我现在已经想出了如何从字面上区分它们。
但我仍然对编译器如何理解指针声明感到困惑。比如有没有int*
这样的类型?
int *p; // a common pointer declaration
具体来说,编译器是如何理解前一句的?先把p
当作一个指针,然后发现指向的对象是int
?或者发现用户声明了一个名为 p
?
的指向 int int*
的指针
面对指向数组的指针时,我更困惑。
int (*p)[4] //a pointer to an array of int[4]
这个怎么理解?编译器是否将其视为 int[4] *p
(int[4]
像我们在容器中所做的那样像新类型一样工作)?以下案例中的类似问题。
int *p[4] //an array-of-pointers
由于 []
先于 *
,编译器是否首先理解 p[4]
并将 p
视为数组(具有未知元素类型),然后指定元素输入 int*
?
声明的解析可以在当前标准的第6.7.6节中找到。它太大了,无法完整介绍,但简而言之,关于 p
类型的规则以 inductive 方式列出。在这些规则中,T
是普通类型(没有 pointers/arrays 等),D
是声明符:
T * D
的定义是,如果T D
中的D
的类型是"something of/to T
",那么[=12的类型=] 是 "something of pointer to T
".
T D[N]
(其中 N 可以是空白或其他各种东西)被定义为表示如果 T D
中 D
的类型将是 "something of T
",那么D
的类型就是"something of/to array (of dimension N
) of T
".
因此您可以看到每个规则都会修改先前应用该规则的结果,直到我们深入到归纳的 "end",这发生在 D
是普通标识符时。
此外,T ( D )
表示 T D
除了强制解析。
一些消息来源将声明描述为正在阅读 "inside out",虽然这个归纳链实际上发生了 "outside in",但您需要进入然后回溯您的结果。作为人类,我们可能被教导阅读的方式与语言定义不同,尽管最终结果是一样的。
要使用您的示例之一,int *p[4]
:
- 规则 1 - 其形式为
T * D
,其中 T
= int
且 D
= p[4]
。由于 T D
将是 "array[4] of int"(见下文),因此 T * D
是 "array[4] of pointer to int".
这一步我们分析了int q[4]
:
- 规则 2 - 其形式为
T D[N]
,其中 T
= int
且 D
= q
。这是 "end case" 因为 D
是一个普通标识符,所以这一步 q
的类型是 "array[4] of int
".
再比如,int (*p)[4]:
- 规则 2 - 这是
T D[N]
的形式,其中 T
= int
,并且 D
= (*p)
。由于 T D
将是 "pointer to int
",因此 T D[4]
是 "pointer to array[4] of int
"。
当我对指向数组的指针和指针数组感到困惑时,我想到了这个问题,尽管我现在已经想出了如何从字面上区分它们。
但我仍然对编译器如何理解指针声明感到困惑。比如有没有int*
这样的类型?
int *p; // a common pointer declaration
具体来说,编译器是如何理解前一句的?先把p
当作一个指针,然后发现指向的对象是int
?或者发现用户声明了一个名为 p
?
int*
的指针
面对指向数组的指针时,我更困惑。
int (*p)[4] //a pointer to an array of int[4]
这个怎么理解?编译器是否将其视为 int[4] *p
(int[4]
像我们在容器中所做的那样像新类型一样工作)?以下案例中的类似问题。
int *p[4] //an array-of-pointers
由于 []
先于 *
,编译器是否首先理解 p[4]
并将 p
视为数组(具有未知元素类型),然后指定元素输入 int*
?
声明的解析可以在当前标准的第6.7.6节中找到。它太大了,无法完整介绍,但简而言之,关于 p
类型的规则以 inductive 方式列出。在这些规则中,T
是普通类型(没有 pointers/arrays 等),D
是声明符:
T * D
的定义是,如果T D
中的D
的类型是"something of/toT
",那么[=12的类型=] 是 "something of pointer toT
".T D[N]
(其中 N 可以是空白或其他各种东西)被定义为表示如果T D
中D
的类型将是 "something ofT
",那么D
的类型就是"something of/to array (of dimensionN
) ofT
".
因此您可以看到每个规则都会修改先前应用该规则的结果,直到我们深入到归纳的 "end",这发生在 D
是普通标识符时。
此外,T ( D )
表示 T D
除了强制解析。
一些消息来源将声明描述为正在阅读 "inside out",虽然这个归纳链实际上发生了 "outside in",但您需要进入然后回溯您的结果。作为人类,我们可能被教导阅读的方式与语言定义不同,尽管最终结果是一样的。
要使用您的示例之一,int *p[4]
:
- 规则 1 - 其形式为
T * D
,其中T
=int
且D
=p[4]
。由于T D
将是 "array[4] of int"(见下文),因此T * D
是 "array[4] of pointer to int".
这一步我们分析了int q[4]
:
- 规则 2 - 其形式为
T D[N]
,其中T
=int
且D
=q
。这是 "end case" 因为D
是一个普通标识符,所以这一步q
的类型是 "array[4] ofint
".
再比如,int (*p)[4]:
- 规则 2 - 这是
T D[N]
的形式,其中T
=int
,并且D
=(*p)
。由于T D
将是 "pointer toint
",因此T D[4]
是 "pointer to array[4] ofint
"。