这是标准规定的吗?
嗯,是的。
§8.3.4/3 当多个“array of”规范相邻时,创建多维数组类型;只有第一个指定数组边界的常量表达式可以省略。除了允许不完整对象类型的声明外,在某些情况下,在函数参数的声明中可以省略数组绑定(8.3.5)。当声明符后跟初始化器(8.5)时,也可以省略数组绑定。在这种情况下,边界是根据提供的初始元素(例如N
)的数量(8.5.1)计算的,标识符的类型D
是“数组N
T
”。此外,如果在指定边界的同一范围内存在实体的先前声明,则省略的数组边界将被视为与先前声明中的相同,并且对于 a 的静态数据成员的定义也是如此班级。
如果是这样,那是为什么?
一方面,不能从不完整的类型(void
例如)构造数组。未知界限数组是这些不完整类型之一:
§8.3.4/1 ...数组类型的对象包含一个连续分配的非空N
类型子对象集T
。除以下说明外,如果省略常量表达式,则标识符的类型D
为“ derived-declarator-type-list array of unknown bound of 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[][] = { ... };
将有未知数量的未知大小的元素。
资源