簡體   English   中英

3D數組如何存儲在C中?

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

我知道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

或者是其他方式? 還是取決於什么?

在較低的層次上,沒有多維數組這樣的東西。 只有一個平坦的內存塊,大到足以容納給定數量的元素。 在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]

所有“尺寸”都連續存儲在存儲器中。

考慮

    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類型)是連續的

是的,你是對的 - 它們是連續存儲的。 考慮這個例子:

#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

是的,它們只是按順序存儲。 您可以像這樣測試:

#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)的多索引數組的訪問將轉換為ondimensional訪問,如下所示:

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

我想你已回答了自己的問題。 多維數組以行主順序存儲。

請參閱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

假設你有一個數組char arr[3][4][5] 它是由3個5個字符陣列組成的3個數組的數組。

為簡單起見,假設arr[x][y][z]xyz而在arr[1][2][3]我們存儲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個字節。

回答OP對主要問題的評論(會有點長,所以我決定回答,而不是評論):

C中的array[ny][nx]是否應聲明為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]a[i+1][j]是N個元素。 通常說“最后一個下標變化最快”,或者通常稱為“按行存儲”:二維矩陣中的一行(即具有相同第一索引的元素)已連續放置在內存中而一列(相同的第二個索引) )由遠離彼此的元素組成。 重要的是要了解性能方面的考慮:訪問鄰居元素通常要快得多(由於HW緩存等),因此例如應該組織嵌套循環,使最內層循環遍歷最后一個索引。

回到問題:如果你的2D數組的心理圖片(抽象)是Carthesian坐標中的格子,那么是的,你可以把它想象成C中的array[NY][NX] 。但是如果你需要描述將真實的2D或3D數據作為數組,索引的選擇可能取決於其他因素:數據格式,方便的符號,性能等。例如,如果位圖的內存中表示是array[NX][NY] in您需要使用的格式,您將以這種方式聲明它,也許您甚至不需要知道位圖變為“轉置”:)

3d數組是擴展的2d數組。

例如,我們有一個數組 - int arr(3)(5)(6);

這是一個由兩個2d數組組成的數組,其中數組將具有4行和3列的2d數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM