如何在C中分配一个三维数组



用C语言创建二维数组很容易:

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

如何在C语言中实现三维数组?它看起来不像我可以这样做:

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

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

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

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

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

 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)

可以使用灵活的数组成员打包所有这些,例如

 struct my3dstring_st {
   int width;
   int length;
   int height;
   char arr[];
 };

则有a.g.a making函数

  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,你可以有不安全但更快的变体,不做任何检查…

一般规则:

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 *arr的结果与sizeof (T) * n * m相同;结果更容易阅读,更不容易出错。

如果你的编译器不支持vla,并且你在编译时不知道你的尺寸,你要么必须分配为1-d数组并手动计算偏移量:

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的结果以确保它成功。你需要按照分配数组的相反顺序释放数组

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

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

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

相关内容

  • 没有找到相关文章

最新更新