无法从多维数组的初始值设定项推断出边界

Failed to deduce bounds from initializer for multi-dimensional arrays

本文关键字:边界 推断出 数组      更新时间:2023-10-16
以下

代码无法编译:

int main() {
  int a[][] = { { 0, 1 },
                { 2, 3 } };
}

生成的错误消息是

error: declaration of 'a' as multidimensional array must have bounds for all dimensions except the first
int a[][] = { { 0, 1 },
           ^

这是标准规定的吗?如果是这样,为什么会这样?我认为在这里推断边界非常容易。

这是标准规定的吗?

是的。

§8.3.4/3 当几个"数组"规范相邻时,a 创建多维数组类型;只有常量中的第一个 可以省略指定数组边界的表达式。在 添加到不完整对象类型为 允许,在某些情况下,数组绑定可能会在 函数参数的声明 (8.3.5)。数组绑定也可以 当声明符后跟初始值设定项 (8.5) 时省略。 在这种情况下,边界是根据初始数计算的 元素(例如,N )提供的 (8.5.1) 和标识符的类型 D是"N T数组"。此外,如果有前面的 在与绑定相同的范围内声明实体 指定时,省略的数组绑定将被视为与 较早的声明,以及类似地用于静态数据的定义 类的成员。

如果是这样,为什么会这样?

首先,数组不能由不完整的类型(例如void)构造。未知边界数组是这些不完整的类型之一:

§8.3.4/1 ...数组类型的对象包含连续分配的对象 类型 T 的非空N子对象集。除非下文另有说明,否则如果 省略常量表达式,标识符的类型为 D 是"派生声明器类型列表数组未知边界的T",一个 不完整的对象类型。...

§8.3.4/2 数组可以从一种基本类型构造 (void 除外 )、从指针、从指针到成员、从 类、枚举类型或另一个数组。

此外:

§3.9 已声明但未定义的类,枚举 在某些上下文 (7.2) 中键入,或未知大小或 不完整的元素类型,是一个不完整定义的对象 类型45 ...

45) 未完全定义的实例的大小和布局 对象类型未知。

我认为在这里推断边界非常容易。

初学者常犯一个错误,编译器具有神奇的力量。编译器使用它已经拥有的信息,它不会凭空创建信息。如果你要求它创建一个未知大小的对象,它根本无法这样做。请参阅以下示例:

只能省略最里面的维度。元素的大小 为数组变量的给定类型推导一个数组。这 因此,元素的类型必须具有已知大小。

  • char a[] = { ... };具有元素(例如 大小为 1(8 位) a[0]),大小未知。
  • char a[6] = { ... }; 具有大小为 1 的元素,大小为 6。
  • char a[][6] = { ... };具有元素(例如 大小为 6 数组a[0],大小未知。
  • char a[10][6] = { ... };具有大小为 6 的元素。 大小为 60。

不允许:

  • char a[10][] = { ... };将有 10 个未知大小的元素。
  • char a[][] = { ... };将具有未知数量的未知大小的元素。