为什么在 C 语言中可以使用数组的数组?这是我在打开 C 标准语言(C17)时遇到的问题。
我发现了一些有趣的东西(6.2.5“类型”/20):
可以从对象和函数类型构造任意数量的派生类型,如下所示: - 数组类型描述具有特定成员对象类型的连续分配的非空对象集,称为元素类型。 只要指定数组类型,元素类型就应该是完整的。 数组类型的特征在于其元素类型和数组中元素的数量。 数组类型被称为从其元素类型派生而来,并且如果其元素类型为 T,则该数组类型有时称为“T 数组”。 从元素类型构造数组类型称为“数组类型派生”。
在 C 语言中,我们有对象类型、函数类型和不完全类型。数组元素是对象类型,而不是派生类型,我心想:“现在怎么办?” 然后我发现了这个(6.7.6.2/1 和 6.7.6.2/3):
-除了可选的类型限定符和关键字 static 之外,[ 和 ] 还可以分隔表达式或*。如果它们分隔表达式(指定数组的大小),则该表达式应为整数类型。如果表达式为常量表达式,则其值应大于零。元素类型不得为不完整类型或函数类型。可选的类型限定符和关键字 static 只能出现在具有数组类型的函数参数的声明中,并且只能出现在最外层的数组类型派生中。
- 如果在声明“T D1”中,D1 具有以下形式之一:D [ 类型限定符列表opt 赋值表达式opt ] D [ 类型限定符列表opt 赋值表达式 ] D [ 类型限定符列表静态赋值表达式 ] D [ 类型限定符列表opt ]并且在声明“TD”中为 ident 指定的类型是“派生声明器类型列表 T”,那么为 ident 指定的类型是“派生声明器类型列表 T 的数组”。144)(有关可选类型限定符和关键字 static 的含义,请参见 6.7.6.3。)
在 6.7.6.2/1 中,我理解元素类型不能是函数类型和不完全类型,但后来我理解元素类型可以是对象类型和派生类型。在 6.7.6.2/3 中,如果类型是派生类型,我们可以创建派生类型的数组。在我看来,数组是可以归类为对象类型的派生类型。但这只是我的观点,我并不认为这是事实。如果我的观点不正确,请解释原因。
看起来你被这句话误导了:
这听起来好像派生类型是与对象和函数类型不同的类型类别。
并非如此。所有类型要么是对象类型,要么是函数类型。派生类型并不妨碍类型成为对象或函数类型。
所有数组类型都是对象类型,因此拥有一个元素类型为另一种数组类型的数组类型是完全可以的。
来自 C23 草案标准 n3220 6.2.5 1:
此处的“分区”指的是类型分为两类:对象类型和函数类型。上文引用的是 C23 标准,但在 C17 和 C11 标准中也可以找到相同的语言。早期的 C99 和 C89 标准也有类似但不完全相同的语言,其划分方案也包含了不完整类型。只有 C11 及更高版本才有对象类型和函数类型,并且对象类型进一步细分为完整对象类型和不完整对象类型。
数组不是函数,而是对象。数组可以拥有(完整的)数组类型成员,因为数组是对象类型。
在 C 语言中,对象和函数可以具有不同的类型。
来自 C 标准(6.2.5 类型,第 1 页):
数组类型只不过是从其他对象类型派生出来的对象类型。具体如下(C 标准 6.2.5 类型):
例如,与数组类型类似,您可以构造不同的指针类型:
如果编译器支持 C23 标准,那么你可以写
也就是说,您可以从已经存在的对象类型构建新的对象类型。