在C17中我们有这个(6.7.6.2 #3):
如果在声明“
T D1
”中,D1
有以下形式之一:
D [
类型限定符列表opt 赋值表达式opt]
D [
类型限定符列表opt 赋值表达式]
D [
类型限定符列表static
赋值表达式]
D [
类型限定符列表opt]
并且声明“ ”中为ident指定的类型
T D
为“派生声明器类型列表 T ”,那么为ident指定的类型 为“ T的派生声明器类型列表数组”。144 ) (有关可选类型限定符和关键字 的含义,请参见 6.7.6.3 。)static
它不是派生的float
,或int
,或char
,它是“数组”,或“指向”。
例如,我们有int name [2][3]
,这里T
是int
,并且D1
是A[2][3]
,形式为D[3]
其中D
是A[2]
,所以T D
是int A[2]
,或“2个int型数组”。那么的声明类型A
为“2个int型数组,3个int型数组”。
但是怎么样int * name[4]
?
这里,“派生声明器类型列表 T ”将是int * name
。而且,事实证明,“派生声明器类型列表T数组”将是一个指向 4 个元素的数组的指针?
最终,这是错误的,因为int *name[4]
它是一个包含4个指针的数组。请解释一下。
OP 对声明的解释
int *name[4];
存在问题,即“'...derived-declarator-list-of-types-T' 将是int *name
”。尽管最终结果是一个数组声明,但 C 语法要求将声明器视为指针声明器,因为 C 语法为 C17 6.7.6.1 中的“* type-qualifier-list opt D”*name[4]
形式提供了特定的语义。给定声明
int *name[4];
,请注意声明符由C17 6.7.6.1§1 指针声明符*name[4]
处理:这里T为
int
,D1为*name[4]
,所以TD为int name[4]
。现在,从C17 6.7.6.2§3 数组声明符开始:
在
int name[4]
T 为int
,且 D1name[4]
为 的情况下,TD 为int name
,其类型为“int
”(C17 6.7.6§5)。最后一句中没有派生声明器类型列表,因此根据 6.7.6.2§3,此处指定的类型name
为“ 的数组”。int
最后回到 6.7.6.1,对于声明符,我们已知
*name[4]
TD 为。应用 6.7.6.2 可知,为inint name[4]
指定的类型为“ 的数组”。由此可见,指针声明符的派生声明符类型列表为“ 的数组”,并且通过应用 6.7.6.1§1 可知,该声明必须声明一个类型为“指向 的指针数组”的对象。name
int name[4]
int
*name[4]
int *name[4];
int
解析
int * name [ 4 ] ;
为声明的过程如下:如果我们从底部开始构建,我们会发现声明说明符仅由一个类型说明符组成,
int
并且初始化声明符列表仅由一个声明符组成。为了达到段落 C17 6.7.6.2/3 的目的,* name [ 4 ]
它们分别是T
和:D1
这是相关规定。 是之前
D
的部分,所以在这种情况下,因此是。D1
[
* name
T
D
int * name
规范要求我们
T
D
单独进行分析,就像分析一个完整的声明一样,以确定它将为标识符 声明的类型name
。在本例中,即int *
(第 6.7.6.1 节),因此它对应于 与分析相关的派生声明器类型列表 T。此时,我们需要认识到,规范没有定义符号derived-declarator-type-list,也没有定义derived-declarator-type或derived-declarator,除非上下文中存在此规定以及指针、函数和声明规范中类似的其他规定typedef
。因此,我们只能将其与第 6.7.6/4-5 段进行协调:请注意,规范中仅使用字体来区分两个独立的“T”符号。其中一个,我将其字体翻译为
T
,表示声明符之前的所有语法组件;而另一个,采用斜体字体,表示 C 语言语义所传达的抽象数据类型T
。现在还要注意,为了
T
D1
表示完整声明的语法形式,必须能够吸收那些对声明的数据类型TT
无关的声明说明符。这些说明符包括存储类说明符(例如 )和函数说明符(例如)等等。这就是我们需要与派生声明器类型列表建立的联系。此符号表示 中所有对指定数据类型T无关的说明符。static
inline
T
现在,我们终于可以认识到,当我们
int *
用派生声明器类型列表 T来解释 our 时,派生声明器类型列表为空,而T是“指向int
”的指针。因此,回到第 6.7.6.2/3 段,整个声明int * name [ 4 ] ;
声明name
为“指向int
”的指针数组。总的来说,这与你可能学过的解释 C 语言声明的程序形式化。根据语法形式,我们认识到,我们需要从
name
,它(仅)指定被声明的标识符,通过name[4]
,另外指定name
一个包含 4 个元素的数组,最后*name[4]
,它另外指定数组的每个元素都是一个指针。