为什么在声明多维数组时允许省略第一维,但不允许省略其他维?

11

为什么在多维数组中不需要提及第一个维度,但必须提及其他维度:

int A[][][2]={{{1,2},{3,4}},{{4,5},{5,6}}}; // error 
int A[][2][2]={{{1,2},{3,4}},{{4,5},{5,6}}}; // OK 

我无法理解这个概念或逻辑背后的原理。


3
请展示一个代码示例以便更清晰地理解你所说的内容。 - πάντα ῥεῖ
1
通常,人们会问这个问题,因为他们打算将多维数组作为参数传递给函数,并希望函数能够处理任何大小的数组。如果是这种情况,我强烈建议您改用向量。 - Christophe
int A[][][2]={{{1,2},{3,4}},{{4,5},{5,6}}} 这里会出错int A[][2][2]={{{1,2},{3,4}},{{4,5},{5,6}}} 这里没问题 - Rishab Shinghal
你是在特别询问声明数组并提供初始化器的情况,还是关于多维数组的一般性问题? - n. m.
3个回答

8

在提到二维数组时,除非它作为函数参数或者有初始化器存在,否则需要同时指明两个维度。如果有初始化器,则第一个维度可以省略。

例如,在函数中使用二维数组作为参数:

int 2D_arr[m][n]   

转换为

int (*2D_arr)[n]  

因此,第一维可以被省略。但是,第二维必须存在,以告诉编译器指针2D_arr是指向包含n个整数的数组的指针。
在第二种情况下,当有初始化程序存在时:
int A[][2][2]={{{1,2},{3,4}},{{4,5},{5,6}}};    

编译器只使用初始化程序的长度来计算第一个维度。其余的维度必须在声明时明确指定。

1
我认为他在问,为什么存在初始化程序时不能推导出更多的维度。 - M.M

7
因为使用多维数组时,计算实际索引会使用除第一维以外的所有维度大小。例如,对于声明为int arr[3][4][5];的3D数组,arr[i][j][k]按定义是*(&(arr[0][0][0]) + k + 5 *(j + 4 * i))
因此,当可以从上下文初始化中推断出第一维,或者在获取函数参数时可能被忽略时,它可以省略。
示例:
int arr[][2] = { 1,2,3,4 };

void setArr(void *container, int arr[][4]);

这是一个基本观点,但更清晰的表述可能是对数组arr[i][j][k]进行取消引用“相当于” arr[i][j][k] = *(&(arr[0][0][0]) + k + 5 *(j + 4 * i)); 而不是将其展示为与声明相同代码的一部分,因为在更多应用程序中无需编写此类行。如果这是我的答案,我会命名数组大小,因为这样很容易阅读,而无需回到声明。 - dmckee --- ex-moderator kitten
@dmckee:你说得对。我没有意识到它看起来像代码...已经编辑过了。 - Serge Ballesta

1
如果您以静态方式声明一个二维数组...
int arr[3][4];

如果您以动态方式声明2D数组,或者将其声明为指向指针的方式...

那么它的两个维度就显而易见了。

int r = 3, c = 4;
int** arr = new int*[r];
for (int i = 0; i < r; i++) {
    arr[i] = new int[c];
}

看起来在分配时只提到了一个维度,但这是因为首先你要分配行,然后是每一列。当你获取或设置元素时,像往常一样指定两个维度...

num = arr[1][2];
arr[1][2] = num;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接