如何在存储器中表示n维(n> = 2)数组?

时间:2011-11-11 02:59:08

标签: c arrays memory-management

任何人都可以为我提供一个公式,以便我能理解像这样"How_are_two-dimensional_arrays_represented_in_memory"的n维(n> = 2)数组的记忆表示吗?

此计算仅适用于2D阵列。

如何计算,假设一个5D阵列?

确定....

我想我找到了答案:Array_data_structure#Two-dimensional_arrays

3 个答案:

答案 0 :(得分:4)

C中的二维数组不过是数组数组。三维数组是数组数组的数组。等等。

C99 standard的相关部分是6.5.2.1,“数组下标”:

  

连续的下标运算符指定a的元素   多维数组对象。如果 E n - 维数组   ( n ≥2),尺寸 i×j×。 。 。 ×k ,然后 E (用作   除了左值之外)转换为指向( n - 的指针 -   1)维度 j×的维数组。 。 。 ×k 。如果一元*   运算符显式应用于此指针,或隐式应用于   下标的结果,结果是指向的( n -   1) - 维数组,如果使用的话,它本身被转换成指针   除了左值之外。由此得出存储阵列   按行主要顺序(最后一个下标变化最快)。

由于指针运算符是根据指针算法定义的,因此引起了一些混淆。这并不意味着数组是“真正的指针” - 实际上它们肯定不是。声明一个数组对象根本不会创建任何指针对象(除非它是一个指针数组)。但是一个引用数组的表达式通常(但不总是)“衰减”到指向数组第一个元素的指针(指针,而不是指针对象

现在简单的数组对象,无论多维,都非常不灵活。在C99之前,所有数组对象必须具有在编译时确定的固定大小。 C99引入了可变长度数组(VLA),但即使如此,VLA的大小在声明时也是固定的(并且并非所有编译器都支持VLA,即使在C99标准发布后12年也是如此)。

如果您需要更灵活的东西,常见的方法是声明指向元素类型的指针,然后使用malloc()分配数组并使指针指向数组的第一个元素:

int *ptr = malloc(N * sizeof *ptr);
if (ptr == NULL) /* handle allocation failure */

这允许您使用与声明的固定大小数组对象相同的语法引用堆分配数组的元素,但在arr[i]中,表达式arr衰减到指针,而在ptr[i]`ptr中,已经指针。

同样的事情可以扩展到更高的维度。您可以分配一个指针数组,然后将每个指针初始化为指向已分配的 的数组的开头。

这给你的东西行为非常像一个二维(或更多)数组,但你必须自己管理内存;这是更大灵活性的代价。

严格地说,这是不是二维数组。如上所述,二维数组仅 数组数组。将其视为二维阵列可能并非完全不合理,但这与C标准中的用法相冲突;它类似于将链表称为一维数组。

comp.lang.c FAQ是一个很好的资源;第6节涵盖了数组和指针,特别出色。

答案 1 :(得分:2)

二维数组实际上是一个指向数组的指针数组。整数a[i][j]的二维数组将占用指针数组i*sizeof(int*),最终数组占用i*j*sizeof(int)

3-D数组a[i1][i2][i3]是指向数组指针数组的指针数组。第一级数组包含i1个指针,第二级包含i1*i2个指针,第三个级别包含i1*i2*i3个整数。

通常,大小为i1..iN的N维数组将具有N-1级别的指针数组和1级的整数数组。 N级数组的长度为iN,该级别有product of i1..iN-1个数组。

所以,一个5-D阵列:

1 array, length i1, of pointers
i1 arrays, length i2, of pointers
i1*i2 arrays, length i3, of pointers
i1*i2*i3 arrays, length i4, of pointers
i1*i2*i3*i4 arrays, length i5, of ints

希望有所帮助(我希望我的指数正确)。

您发布的维基百科链接指的是/不同类型的多维数组/。默认情况下,C多维数组就是我刚才描述的方式。您还可以将它们抽象为单维数组。这节省了内存并使整个数组连续,但它使访问元素更复杂一些。对于5-D示例:

// WARNING I AM CHANGING NOTATION. N1..N5 are the lengths in each direction.
// i1..i5 are the indicies.
int* bigarray = malloc(sizeof(int)*N1*N2*N3*N4*N5);
// now instead of bigarray[i1][i2][i3][i4][i5], write this:
*(bigarray + i1*N2*N3*N4*N5 + i2*N3*N4*N5 + i3*N4*N5 + i4*N5 + i5);

每个术语的偏移量乘以我们需要偏移的元素数量。例如,要增加一个第一维级别,我们需要遍历剩下的四个维度以“环绕”,如果愿意的话。

答案 2 :(得分:1)

如我记得的那样,数组如何存储在C的内存中并不是标准化的。但是有关数组的一些信息以及它们如何存储在内存中,请参阅以下两个链接:

http://webster.cs.ucr.edu/AoA/Windows/HTML/Arraysa2.html

http://publications.gbdirect.co.uk/c_book/chapter5/arrays.html

第一个链接更通用,讨论了存储数组的不同方法,而第二个链接讨论了C数组在内存中布局的最可能方式。