以下代码无法编译:
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 },
^
这是由标准规定的吗?如果是这样,为什么呢?我认为在这里推算界限非常容易。
答案 0 :(得分:3)
这是由标准指定的吗?
嗯,是的。
§8.3.4/ 3当几个“数组”规范相邻时,a 创建多维数组类型;只有第一个常数 可以省略指定数组边界的表达式。在 除了不完整的对象类型的声明之外 允许,在某些情况下可以省略数组绑定 声明函数参数(8.3.5)。数组绑定也可以 当声明符后跟初始值设定项(8.5)时,将省略。 在这种情况下,边界是从初始数量计算的 提供的元素(例如,
N
)(8.5.1),以及标识符的类型D
的“N
T
数组”。此外,如果有前一个 声明与该界限相同的实体的声明 指定时,省略的数组绑定与其中的相同 早期声明,类似于静态数据的定义 班级成员。
如果是这样,为什么会这样?
首先,不能用不完整的类型(例如void
)构造数组。未知边界的数组是这些不完整类型之一:
§8.3.4/ 1 ...数组类型的对象包含一个连续分配的对象 类型为
N
的非空T
子对象集。除非如下所述,否则 省略常量表达式,D
标识符的类型 是“ derived-declarator-type-list 未知范围T
”的数组, 不完整的对象类型...§8.3.4/ 2可以从一种基本类型构造一个数组 (除了
void
),从指针,指向成员的指针,从 class,枚举类型或其他数组。
此外:
§3.9已声明但未定义的类,枚举 键入某些上下文(7.2),或未知大小的数组或 不完整的元素类型,是未完全定义的对象 输入。 45 ...
45)未完全定义的实例的大小和布局 对象类型未知。
我认为在这里演绎界限非常容易。
初学者犯了一个常见错误,即编译器具有神奇的力量。编译器使用已经的信息,它不会凭空创建信息。如果您要求它创建一个未知大小的对象,它根本无法这样做。请参阅以下示例:
只能省略最里面的尺寸。元素的大小 推导出为数组变量赋予的类型的数组。该 因此,元素的类型必须具有已知的大小。
char a[] = { ... };
包含大小 1(8位)的元素(例如a[0]
),且大小未知。char a[6] = { ... };
的元素大小 1,大小为6。char a[][6] = { ... };
包含元素(例如a[0]
,这是一个数组)大小 6,且大小未知。char a[10][6] = { ... };
的元素大小 6.并且大小为60。不允许:
char a[10][] = { ... };
将有10个未知大小。char a[][] = { ... };
将包含未知数量未知大小的元素。