How are 3D arrays stored in C?

前端 未结 8 2188
半阙折子戏
半阙折子戏 2020-11-29 23:17

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

相关标签:
8条回答
  • 2020-11-29 23:28

    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

    0 讨论(0)
  • 2020-11-29 23:30

    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.

    0 讨论(0)
  • 2020-11-29 23:33

    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]
    
    0 讨论(0)
  • 2020-11-29 23:42

    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

    0 讨论(0)
  • 2020-11-29 23:45

    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 讨论(0)
  • 2020-11-29 23:45

    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]
    
    0 讨论(0)
提交回复
热议问题