如何在C中分配3维数组?

时间:2014-07-21 21:03:19

标签: c arrays malloc

在C中创建二维数组很简单:

char (*arr)[50] = malloc(sizeof(arr) * 10 * 50); // 10x50 matrix

你如何用C做三维数组?我看起来不像以下那样:

char (**arr)[50] = malloc(sizeof(arr) * 10 * 20 * 50); // 10x20x50 matrix?

4 个答案:

答案 0 :(得分:3)

三维数组需要知道2个维度

char (*arr)[20][50] = malloc(sizeof(char) * 10 * 20 * 50)

注意:我已将sizeof(arr)更正为sizeof(char),因为sizeof(arr)将返回指针的大小。

答案 1 :(得分:1)

可能的方法是分配一维数组,例如

 int width=10; length=20; height=50;
 char* arr = malloc(width*length*height);
 if (!arr) { perror("malloc"); exit(EXIT_FAILURE); };

然后有一些方法来访问它,例如宏

 #define Element(I,J,K) arr[width*length*(I)+length*(J)+(K)]

并使用Element(i,j,k)

您可以使用flexible array member之类的

打包所有这些内容
 struct my3dstring_st {
   int width;
   int length;
   int height;
   char arr[];
 };

然后有一个。制作功能

  struct my3dstring_st *
  make_my3dstring (int width, int length, int height)
  { 
    if (width<=0 || length<=0 || height<=0) return NULL;
    struct my3dstring_st* s = 
       malloc(sizeof(struct my3dstring_st) 
              + width * length * height);
    if (!s) {perror("malloc"); exit(EXIT_FAILURE); };
    s->width = width;
    s->length = length;
    s->height = height;
    memset (s->arr, 0, width * length * height);
    return s;
  }

和内联访问功能(在头文件中):

  static inline int 
  access_m3dstring(struct my3dstring_st*s, int i, int j, int k) {
     if (!s || i<0 || j<0 || k<0 
         || i>=s->width || j>=s->height || k>=s->length) return EOF;
     return s->arr[i*->width*s->height + j*s->height + k];
   }

我作为练习留下来编写修改函数modify_m3dstring,你可能会有不安全但速度更快的变种,不做任何检查......

答案 2 :(得分:1)

一般规则:

T *arr         = malloc( sizeof *arr * n ); // for an N-element array
T (*arr)[N]    = malloc( sizeof *arr * m ); // for an NxM-element array
T (*arr)[N][M] = malloc( sizeof *arr * k ); // for an NxMxK-element array

其中大写字母表示在编译时已知的值,小写字母表示在运行时已知的值。高维数组的模式应该是显而易见的。

如果您使用的是C99编译器或支持可变长度数组的C2011编译器,则可以对所有维使用运行时变量:

size_t n = some_value();
size_t m = some_other_value();
size_t k = yet_another_value();

T (*arr)[n][m] = malloc( sizeof *arr * k );

表达式*arr的类型为T [n][m],因此sizeof *arrsizeof (T) * n * m的结果相同;结果更容易阅读,更不容易出错。

如果您的编译器不支持VLA并且您在编译时不知道您的维度,那么您必须分配为一维数组并手动计算偏移量:

T *arr = malloc( sizeof *arr * n * m * k );
...
arr[ 3*n*m + 2*m + 1] = x; // equivalient to arr[3][2][1] = x

或者,如果你可以忍受在内存中不相邻的行,你可以零散地分配数组:

T ***arr = malloc (sizeof *arr * n );
for (size_t i = 0; i < n; i++ )
{
  arr[i] = malloc( sizeof *arr[i] * m );
  for (size_t j = 0; j < m; j++ )
  {
    arr[i][j] = malloc( sizeof *arr[i][j] * k )
  }
}

理想情况下,您应该检查每个malloc的结果,以确保它成功。而且你必须按照你分配它的相反顺序释放数组:

答案 3 :(得分:0)

char (*arr)[20][50] = malloc(sizeof(char) * 10 * 20 * 50);

sizeof(char)保证为1.因此,它可以省略。

char (*arr)[20][50] = malloc(10 * 20 * 50);