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

发布于 2024-11-05 19:12:44 字数 374 浏览 1 评论 0原文

据我所知,C 中的数组是按行优先顺序分配的。因此,对于 2 x 3 数组:

0  1
2  3
4  5

存储在内存中为

0 1 2 3 4 5

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

0  1
2  3
4  5

这些如何

6  7
8  9
10 11

存储在内存中?只是连续的,例如:

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

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

I understand that arrays in C are allocated in row-major order. Therefore, for a 2 x 3 array:

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:

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

风渺 2024-11-12 19:12:44

在低层次上,不存在多维数组这样的东西。只有一块平坦的内存块,足够大以容纳给定数量的元素。在 C 语言中,多维数组在概念上是其元素也是数组的数组。因此,如果您这样做:

int array[2][3];

从概念上讲,您最终会得到:

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

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

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

...将为您提供如下结构:

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

继续在内存中连续排列元素(如上所述,只有 [0, 1] 条目实际上占用内存中的空间,其他所有内容只是对这些条目之一的引用的一部分)。正如您所看到的,无论您有多少个维度,这种模式都会持续下去。

只是为了好玩:

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

给你:

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]

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. 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. Note that this means that only the [0, 1, 2] entries actually occupy space in memory. 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). 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]
烟─花易冷 2024-11-12 19:12:44

所有“维度”都连续存储在内存中。

假设

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

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

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
or that arr[1][42] and arr[1][43] (of type int[20]) are contiguous
or that arr[1][42][7] and arr[1][42][8] (of type int) are contiguous

柠栀 2024-11-12 19:12:44

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

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

输出:

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

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

奈何桥上唱咆哮 2024-11-12 19:12:44

是的,它们只是按连续顺序存储。您可以这样测试:

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

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

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

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:

array[i][j][k] = array[M*L*i + L*j + k]
Bonjour°[大白 2024-11-12 19:12:44

我想你已经回答了你自己的问题。多维数组按行优先顺序存储。

参见ANSI C规范第3.3.2.1节(还有一个具体的例子):

连续的下标运算符指定一个成员
多维数组对象。如果 E 是一个 n 维数组 ( n
=2) 尺寸为 ixj "x ... x" k ,然后 E (用作除
左值)转换为指向 ( n -1) 维数组的指针
尺寸 j "x ... x" k 。如果一元 * 运算符应用于此
指针显式地或隐式地作为下标的结果,
result 是指向 ( n -1) 维的数组,它本身是
如果用作左值以外的用途,则转换为指针。如下:
由此可知数组按行主序存储(最后一个下标
变化最快)。

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

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):

Successive subscript operators designate a member of a
multi-dimensional array object. If E is an n -dimensional array ( n
=2) with dimensions i x j "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 . 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. 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

神经大条 2024-11-12 19:12:44

假设您有一个数组 char arr[3][4][5]。它是一个由 3 个数组组成的数组,每个数组由 4 个 5 个字符的数组组成。

为简单起见,假设 arr[x][y][z] 中的值为 xyz ,而 arr[1][2][3] 中的值为 xyz 我们存储123

所以内存中的布局是:

  |  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]arr[2]依次到来,但是每一个中的元素的类型为 char[4][5](这些是表中的三行)。

arr[x][0] - arr[x][3] 也是依次出现,其中的每个元素都是 char[5] 类型(那些是表中每一行的四个部分,000 - 004 是 arr[0][0] 的一个元素 )

arr[x][y][0] - arr[x ][y][4] 是依次出现的 5 个字节。

Let's say you have an array char arr[3][4][5]. It is an array of 3 arrays of 4 arrays of 5 chars.

For simplicity, let's say that the value in arr[x][y][z] is xyz and in arr[1][2][3] we store 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[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][y][0] - arr[x][y][4] are 5 bytes that are coming one after another.

夏夜暖风 2024-11-12 19:12:44

回答OP对主要问题的评论(它会有点长,所以我决定给出答案,而不是评论):

C 中的数组是否应该声明为 array[ny][nx],其中 nynx 是 y 中的元素数量和x方向。此外,这是否意味着我的 3D 数组应该声明为 array[nz][ny][nx]?

在数学中,MxN 矩阵有 M 行和 N 列。矩阵元素的常用表示法是a(i,j), 1<=i<=M, 1<=j<=N。所以你问题中的第一个矩阵是 3x2 矩阵。

事实上,它与通常用于 GUI 元素等的符号不同。 800x600 位图水平方向(沿 X 轴)有 800 个像素,垂直方向(沿 Y 轴)有 600 个像素。如果有人想将其描述为矩阵,那么用数学表示法来说,它将是一个 600x800 矩阵(600 行,800 列)。

现在,C 中的多维数组在内存中的存储方式是 a[i][j+1] 紧邻 a[i][j],而 < code>a[i+1][j] 距离 N 个元素。通常说“最后一个下标变化最快”,或者通常称为“按行存储”:二维矩阵中的一行(即具有相同第一个索引的元素)连续放置在内存中,而一列(相同的第二个索引) )由彼此远离的元素组成。出于性能考虑,了解这一点很重要:对邻居元素的访问通常要快得多(由于硬件缓存等),因此,例如,应组织嵌套循环,以便最里面的循环遍历最后一个索引。

回到问题:如果你心目中的二维数组(抽象)是笛卡尔坐标中的格子,那么是的,你可以将其视为 C 中的 array[NY][NX]但是,如果您需要将真实的 2D 或 3D 数据描述为数组,则索引的选择可能取决于其他因素:数据格式、方便的表示法、性能等。例如,如果位图的内存中表示为 < 。 code>array[NX][NY] 以您需要使用的格式,您将这样声明它,也许您甚至不需要知道位图变得有点“转置”:)

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):

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. Furthermore, does that mean that my 3D array should be declared as array[nz][ny][nx]?

In math, a MxN matrix has M rows and N columns. A usual notation for a matrix element is a(i,j), 1<=i<=M, 1<=j<=N. So the first matrix in your question is a 3x2 matrix.

Indeed it is different from the notation typically used for e.g. GUI elements. A 800x600 bitmap has 800 pixels horizontally (along X axis) and 600 pixels vertically (along Y axis). If some would want to describe it as a matrix, in math notation it would be a 600x800 matrix (600 rows, 800 columns).

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. It is usually said that "the last subscript varies fastest", or often as "stored by rows": a row (i.e. 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.

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" :)

蒗幽 2024-11-12 19:12:44

3d 数组是一个扩展的 2d 数组。

例如我们有一个数组 -
int arr(3)(5)(6);

这是一个由两个 2d 数组组成的数组,其中 array 将有一个 4 行 3 列的 2d 数组。

3d array is an extended 2d array.

For example we have an array -
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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文