3D数组如何存储在C中?

rob*_*ntw 38 c arrays low-level

我知道C中的数组是按行主顺序分配的.因此,对于2 x 3阵列:

0  1
2  3
4  5
Run Code Online (Sandbox Code Playgroud)

存储在内存中

0 1 2 3 4 5
Run Code Online (Sandbox Code Playgroud)

但是,如果我有一个2 x 3 x 2阵列怎么办:

0  1
2  3
4  5
Run Code Online (Sandbox Code Playgroud)

6  7
8  9
10 11
Run Code Online (Sandbox Code Playgroud)

这些如何存储在内存中?只是连续像:

0 1 2 3 4 5 6 7 8 9 10 11
Run Code Online (Sandbox Code Playgroud)

或者是其他方式?还是取决于什么?

aro*_*oth 26

在较低的层次上,没有多维数组这样的东西.只有一个平坦的内存块,大到足以容纳给定数量的元素.在C中,多维数组在概念上是一个数组,其元素也是数组.所以,如果你这样做:

int array[2][3];
Run Code Online (Sandbox Code Playgroud)

从概念上讲,你最终得到:

array[0] => [0, 1, 2]
array[1] => [0, 1, 2]
Run Code Online (Sandbox Code Playgroud)

这导致元素在存储器中连续排列,因为实际上array[0]array[1]没有保存任何数据,它们只是对两个内部数组的引用.请注意,这意味着只有[0, 1, 2]条目实际占用内存空间.如果将此模式扩展到下一个维度,您可以看到:

int array[2][3][2];
Run Code Online (Sandbox Code Playgroud)

...会给你一个像这样的结构:

array[0] => [0] => [0, 1]
            [1] => [0, 1]
            [2] => [0, 1]
array[1] => [0] => [0, 1]
            [1] => [0, 1]
            [2] => [0, 1]
Run Code Online (Sandbox Code Playgroud)

继续在内存中连续排列元素(如上所述,只有[0, 1]条目实际占用内存中的空间,其他所有内容只是对其中一个条目的引用的一部分).如您所见,无论您拥有多少维度,此模式都将继续.

而且只是为了好玩:

int array[2][3][2][5];
Run Code Online (Sandbox Code Playgroud)

给你:

array[0] => [0] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]
            [1] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]
            [2] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]
array[1] => [0] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]
            [1] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]
            [2] => [0] => [0, 1, 2, 3, 4]
                   [1] => [0, 1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)


pmg*_*pmg 18

所有"尺寸"都连续存储在存储器中.

考虑

    int arr[4][100][20];
Run Code Online (Sandbox Code Playgroud)

你可以说,arr[1]arr[2](类型int[100][20])是连续的
,或者arr[1][42]arr[1][43](类型int[20])是连续的
,或者arr[1][42][7]arr[1][42][8](类型int)是连续


sje*_*397 13

是的,你是对的 - 它们是连续存储的.考虑这个例子:

#include <stdio.h>

int array3d[2][3][2] = {
  {{0, 1}, {2, 3}, {3, 4}},
  {{5, 6}, {7, 8}, {9, 10}}
};

int main()
{
  int i;
  for(i = 0; i < 12; i++) {
    printf("%d ", *((int*)array3d + i));
  }
  printf("\n");
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

0 1 2 3 3 4 5 6 7 8 9 10


Thi*_*cke 8

是的,它们只是按顺序存储.您可以像这样测试:

#include <stdio.h>

int main (int argc, char const *argv[])
{
  int numbers [2][3][4] = {{{1,2,3,4},{5,6,7,8},{9,10,11,12}}
                          ,{{13,14,15,16},{17,18,19,20},{21,22,23,24}}};

  int i,j,k;

  printf("3D:\n");
  for(i=0;i<2;++i)
    for(j=0;j<3;++j)
      for(k=0;k<4;++k)
        printf("%i ", numbers[i][j][k]);

  printf("\n\n1D:\n");
  for(i=0;i<24;++i)
    printf("%i ", *((int*)numbers+i));

  printf("\n");

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

这意味着对具有维度(N,M,L)的多索引数组的访问将转换为ondimensional访问,如下所示:

array[i][j][k] = array[M*L*i + L*j + k]
Run Code Online (Sandbox Code Playgroud)


Cod*_*her 6

我想你已回答了自己的问题.多维数组以行主顺序存储.

请参阅ANSI C规范第3.3.2.1节(还有一个具体示例):

连续的下标运算符指定多维数组对象的成员.如果E是具有维度ixj"x ... x"k的n维数组(n = 2),则E(用作除左值之外的值)被转换为指向(n-1)维数组的指针尺寸为j"x ... x"k.如果将unary*运算符显式地应用于此指针,或者由于下标而隐式应用于该指针,则结果是指向的(n-1)维数组,如果将其用作除左值之外的其他数据本身将转换为指针.由此得出,数组以行主要顺序存储(最后一个下标变化最快).

对于您的示例,您可以尝试一下并查看 - http://codepad.org/10ylsgPj