简体   繁体   English

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

[英]How are 3D arrays stored in C?

I understand that arrays in C are allocated in row-major order. 我知道C中的数组是按行主顺序分配的。 Therefore, for a 2 x 3 array: 因此,对于2 x 3阵列:

0  1
2  3
4  5

Is stored in memory as 存储在内存中

0 1 2 3 4 5

However, what if I have a 2 x 3 x 2 array: 但是,如果我有一个2 x 3 x 2阵列怎么办:

0  1
2  3
4  5

and

6  7
8  9
10 11

How are these stored in memory? 这些如何存储在内存中? Is just consecutive like: 只是连续像:

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

Or is it some other way? 或者是其他方式? Or does it depend on something? 还是取决于什么?

At a low level, there is no such thing as a multi-dimensional array. 在较低的层次上,没有多维数组这样的东西。 There is just a flat block of memory, large enough to hold a given number of elements. 只有一个平坦的内存块,大到足以容纳给定数量的元素。 In C, a multi-dimensional array is conceptually an array whose elements are also arrays. 在C中,多维数组在概念上是一个数组,其元素也是数组。 So if you do: 所以,如果你这样做:

int array[2][3];

Conceptually you end up with: 从概念上讲,你最终得到:

array[0] => [0, 1, 2]
array[1] => [0, 1, 2]

This results in the elements being arranged contiguously in memory, because array[0] and array[1] are not actually holding any data, they are just references to the two inner arrays. 这导致元素在内存中连续排列,因为array[0]array[1]实际上并不包含任何数据,它们只是对两个内部数组的引用。 Note that this means that only the [0, 1, 2] entries actually occupy space in memory. 请注意,这意味着只有[0, 1, 2]条目实际占用内存空间。 If you extend this pattern out to the next dimension, you can see that: 如果将此模式扩展到下一个维度,您可以看到:

int array[2][3][2];

...will give you a structure like: ...会给你一个像这样的结构:

array[0] => [0] => [0, 1]
            [1] => [0, 1]
            [2] => [0, 1]
array[1] => [0] => [0, 1]
            [1] => [0, 1]
            [2] => [0, 1]

Which continues arranging the elements consecutively in memory (as above, only the [0, 1] entries actually occupy space in memory, everything else is just part of a reference to one of these entries). 继续在内存中连续排列元素(如上所述,只有[0, 1]条目实际占用内存中的空间,其他所有内容只是对这些条目之一的引用的一部分)。 As you can see, this pattern will continue no matter how many dimensions you have. 如您所见,无论您拥有多少维度,此模式都将继续。

And just for fun: 而且只是为了好玩:

int array[2][3][2][5];

Gives you: 给你:

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]

All "dimensions" are stored consecutively in memory. 所有“尺寸”都连续存储在存储器中。

Consider 考虑

    int arr[4][100][20];

you can say that arr[1] and arr[2] (of type int[100][20] ) are contiguous 你可以说arr[1]arr[2] (类型为int[100][20] )是连续的
or that arr[1][42] and arr[1][43] (of type int[20] ) are contiguous 或者arr[1][42]arr[1][43] (类型为int[20] )是连续的
or that arr[1][42][7] and arr[1][42][8] (of type int ) are contiguous 或者arr[1][42][7]arr[1][42][8]int类型)是连续的

Yep, you're right - they are stored consecutively. 是的,你是对的 - 它们是连续存储的。 Consider this example: 考虑这个例子:

#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;
}

Output: 输出:

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

Yes, they're are just stored in consecutive order. 是的,它们只是按顺序存储。 You can test that like this: 您可以像这样测试:

#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;
}

That means that accesses to a multiindexed array with dimensions (N,M,L) are transformed to onedimensional accesses like this: 这意味着对具有维度(N,M,L)的多索引数组的访问将转换为ondimensional访问,如下所示:

array[i][j][k] = array[M*L*i + L*j + k]

I think you have answered your own question. 我想你已回答了自己的问题。 Multi-dimensional arrays are stored in row-major order. 多维数组以行主顺序存储。

See ANSI C specification section 3.3.2.1 (there is also a specific example): 请参阅ANSI C规范第3.3.2.1节(还有一个具体示例):

Successive subscript operators designate a member of a multi-dimensional array object. 连续的下标运算符指定多维数组对象的成员。 If E is an n -dimensional array ( n =2) with dimensions ixj "x ... x" k , then E (used as other than an lvalue) is converted to a pointer to an ( n -1)-dimensional array with dimensions j "x ... x" k . 如果E是具有维度ixj“x ... x”k的n维数组(n = 2),则E(用作除左值之外的值)被转换为指向(n-1)维数组的指针尺寸为j“x ... x”k。 If the unary * operator is applied to this pointer explicitly, or implicitly as a result of subscripting, the result is the pointed-to ( n -1)-dimensional array, which itself is converted into a pointer if used as other than an lvalue. 如果将unary *运算符显式地应用于此指针,或者由于下标而隐式应用于该指针,则结果是指向的(n-1)维数组,如果将其用作除左值之外的其他数据本身将转换为指针。 It follows from this that arrays are stored in row-major order (last subscript varies fastest). 由此得出,数组以行主要顺序存储(最后一个下标变化最快)。

For your example, you can just try it out and see - http://codepad.org/10ylsgPj 对于您的示例,您可以尝试一下并查看 - http://codepad.org/10ylsgPj

Let's say you have an array char arr[3][4][5] . 假设你有一个数组char arr[3][4][5] It is an array of 3 arrays of 4 arrays of 5 chars. 它是由3个5个字符阵列组成的3个数组的数组。

For simplicity, let's say that the value in arr[x][y][z] is xyz and in arr[1][2][3] we store 123 . 为简单起见,假设arr[x][y][z]xyz而在arr[1][2][3]我们存储123

So the layout in memory is: 所以内存中的布局是:

  |  00  01  02  03  04  05  06  07  08  09  10  11  12  13  14  15  16  17  18  19
--+--------------------------------------------------------------------------------   
00| 000 001 002 003 004 010 011 012 013 014 020 021 022 023 024 030 031 032 033 034 
20| 100 101 102 103 104 110 111 112 113 114 120 121 122 123 124 130 131 132 133 134 
40| 200 201 202 203 204 210 211 212 213 214 220 221 222 223 224 230 231 232 233 234

arr[0] , arr[1] and arr[2] are coming one after another, but each element in the is of type char[4][5] (those are the three rows in the table). arr[0]arr[1]arr[2]一个接一个地出现,但是char[4][5]类型中的每个元素(这些是表中的三行)。

arr[x][0] - arr[x][3] are also coming one after another, and each element in them is of type char[5] (those are the four parts of each line in the table, 000 - 004 is one element of arr[0][0] ) arr[x][0] - arr[x][3]也是一个接一个地出现,其中的每个元素都是char[5]类型(这些是表中每行的四个部分,000 - 004是arr[0][0]一个元素

arr[x][y][0] - arr[x][y][4] are 5 bytes that are coming one after another. arr[x][y][0] - arr[x][y][4]是一个接一个地出现的5个字节。

To answer OP's comment to the main question (it will be somewhat long, so I decided to go with an answer, not a comment): 回答OP对主要问题的评论(会有点长,所以我决定回答,而不是评论):

Should arrays in C be declared as array[ny][nx] where ny and nx are the number of elements in the y and x direction. C中的array[ny][nx]是否应声明为array[ny][nx] ,其中nynx是y和x方向上的元素数。 Furthermore, does that mean that my 3D array should be declared as array[nz][ny][nx] ? 此外,这是否意味着我的3D数组应该声明为array[nz][ny][nx]

In math, a MxN matrix has M rows and N columns. 在数学中,MxN矩阵具有M行和N列。 A usual notation for a matrix element is a(i,j), 1<=i<=M, 1<=j<=N . 矩阵元素的通常标记是a(i,j), 1<=i<=M, 1<=j<=N So the first matrix in your question is a 3x2 matrix. 所以你问题中的第一个矩阵是3x2矩阵。

Indeed it is different from the notation typically used for eg GUI elements. 实际上,它与通常用于例如GUI元素的符号不同。 A 800x600 bitmap has 800 pixels horizontally (along X axis) and 600 pixels vertically (along Y axis). 800x600位图水平(沿X轴)具有800个像素,垂直(沿Y轴)具有600个像素。 If some would want to describe it as a matrix, in math notation it would be a 600x800 matrix (600 rows, 800 columns). 如果有人想将其描述为矩阵,那么在数学符号中它将是600x800矩阵(600行,800列)。

Now, multidimensional arrays in C are stored in memory in such a way that a[i][j+1] is next to a[i][j] while a[i+1][j] is N elements away. 现在,C中的多维数组以这样的方式存储在存储器中: a[i][j+1]紧挨a[i][j]a[i+1][j]是N个元素。 It is usually said that "the last subscript varies fastest", or often as "stored by rows": a row (ie elements with same first index) in a 2-dimensional matrix has placed contiguously in memory while a column (same second index) consist of elements lying far away from each other. 通常说“最后一个下标变化最快”,或者通常称为“按行存储”:二维矩阵中的一行(即具有相同第一索引的元素)已连续放置在内存中而一列(相同的第二个索引) )由远离彼此的元素组成。 It is important to know for performance considerations: access to neighbor elements is usually much faster (due to HW caches etc.), so for example nested loops should be organized such that the innermost one iterates over the last index. 重要的是要了解性能方面的考虑:访问邻居元素通常要快得多(由于HW缓存等),因此例如应该组织嵌套循环,使最内层循环遍历最后一个索引。

Back to the question: if your mental picture (abstraction) of a 2D array is that of a lattice in Carthesian coordinates, then yes, you may think of it as array[NY][NX] in C. However if you need to describe real 2D or 3D data as an array, the choice of indexes probably depends on other things: data formats, convenient notation, performance, etc. For example, if the in-memory representation for a bitmap is array[NX][NY] in a format you need to work with, you will declare it that way, and maybe you don't even need to know that the bitmap becomes sort of "transposed" :) 回到问题:如果你的2D数组的心理图片(抽象)是Carthesian坐标中的格子,那么是的,你可以把它想象成C中的array[NY][NX] 。但是如果你需要描述将真实的2D或3D数据作为数组,索引的选择可能取决于其他因素:数据格式,方便的符号,性能等。例如,如果位图的内存中表示是array[NX][NY] in您需要使用的格式,您将以这种方式声明它,也许您甚至不需要知道位图变为“转置”:)

3d array is an extended 2d array. 3d数组是扩展的2d数组。

For example we have an array - int arr(3)(5)(6); 例如,我们有一个数组 - int arr(3)(5)(6);

This is an array which consists of two 2d arrays where array would have a 2d array having 4 rows and 3 columns. 这是一个由两个2d数组组成的数组,其中数组将具有4行和3列的2d数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM