它是在那里被定义的。这是一种将之前T
遇到的任何东西带到下一个类型的方式,类似于:
<some stuff> T
<some stuff> reference to T
它只是T
在类型中出现的任何内容T D1
。
例如,如果您有声明int& (*const * p)[30]
, T
is int
, D
is& (*const * p)[30]
和D1
is (*const * p)[30]
。的类型T D1
是“指向 30 int 数组的 const 指针的指针”。因此,根据您引用的规则,类型p
是“指向 const 的指针,指向 30 引用 int 的数组的指针”。
当然,此声明随后被 §3.4.2/5 禁止:
不应有对引用的引用,没有引用数组,也没有指向引用的指针。
我认为它是派生声明类型列表的非正式术语来自 C 标准对派生类型的定义(类似于 C++ 中的复合类型):
可以从对象、函数和不完整类型构造任意数量的派生类型,如下所示:
- 数组类型[...]
- 结构类型[...]
- 联合类型[...]
- 函数类型[...]
- 指针类型[...]
回应评论:您似乎对类型和声明符感到困惑。例如,如果int* p
是声明符,那么类型p
是“指向 int 的指针”。类型表示为这些类似英语的句子。
示例 1:int *(&p)[30]
这是一个声明T D
,其中(§8.3.1 指针):
D
具有以下形式:
*
属性说明符序列选择 cv 限定符序列选择 D1
D1
在哪里(&p)[3]
。这意味着具有“对数组 3 的引用”类型T D1
的形式(您可以递归地解决这个问题,下一步使用 §8.3.4 数组等)。之前的所有内容都是derived-declarator-type-list。所以我们可以推断在我们的原始声明中具有类型“对 3 指针数组的引用”。魔法!int (&p)[3]
int
int
p
int
示例 2:float (*(*(&e)[10])())[5]
这是一个声明T D
,其中(§8.3.4 数组):
T
->float
D
->(*(*(&e)[10])())[5]
D
形式为:
D1 [
常量表达式选择 ]
属性说明符序列选择
D1
在哪里(*(*(&e)[10])())
。这意味着T D1
的形式是float (*(*(&e)[10])())
“引用 10 个指针的数组,指向 () 返回指向浮点的指针的函数”(您可以通过应用 §8.3/6 然后 §8.3.1 指针等来计算)。之前的所有float
内容都是derived-declarator-type-list。所以我们可以推断p
在我们的原始声明中具有类型“对 10 的数组的引用,指向 () 的函数的指针,返回指向 5 浮点数组的指针”。又是魔法!