在 C 中为 3 维数组分配空间

Vah*_*yan 2 c arrays pointers dynamic-memory-allocation

这个问题已经在这里得到回答,但对我来说,有些事情仍然悬而未决,而且讨论太旧了,任何人都无法回复评论,此外我想问我的实现中出了什么问题。

无论如何,问题设置。我想为 3D 维度数组分配空间3, h, w。我在做什么:

int ***a = (int***)malloc(3 * sizeof(int*));
for (int i = 0; i < 3; i++)
{
   a[i] = (int **) malloc(height * sizeof(int*)); 
}
Run Code Online (Sandbox Code Playgroud)

我理解这是为三个 3 创建第一个空间int**,然后分配高度int**;然后 :

for (int i = 0; i < 3; i++)
{
  a[i][0] = (int *) malloc(height * width * sizeof(int *));
  for (int j = 1; j < height; j++)
   {
     a[i][j] = a[i][j-1] + width;
   }
}
Run Code Online (Sandbox Code Playgroud)

所以现在我认为每个a[i][0]基本上都是大小为高度和宽度的二维数组的空间;a[i][j]此外, for的其余部分j != 0被初始化为;j th的行a[i][0]

然后我通过以下方式初始化值:

for (int c = 0; c < 3; c++){
  for (int i = 0; i < height; i++){
    for (int j = 0; j < width; j++){
      a[c][i][j] = i+j+c;
Run Code Online (Sandbox Code Playgroud)

然而,这是不正确的。我想将其作为按以下方式分配二维数组的扩展练习:

int *a[height]; 
a[0] = (int*)malloc(height * width * sizeof(int));
for (int i = 1; i < height; i++){
  a[i] = a[i-1] + widht;
}
Run Code Online (Sandbox Code Playgroud)

这样, a 是一个长度为 height 的指针数组,a[0]被分配给整个 2D 数组,后续的指针指向它们各自的行,我可以简单地通过调用来写入它们a[i][j] = some number;

我想做的是将这个 2D 想法扩展到 3D 案例,但遗憾的是我失败了。

Lun*_*din 5

int ***a = (int***)malloc(3 * sizeof(int*));
Run Code Online (Sandbox Code Playgroud)

这不会分配任何有意义的东西。特别是,它不分配 3D 数组,甚至不分配 3D 数组的一部分。它为3个整数指针分配空间,这没有任何意义。a 也没有int***任何意义。

相反,分配一个 3D 数组:

int (*a)[y][z] = malloc( sizeof(int[x][y][z]) );

for(int i=0; i<x; i++)
  for(int j=0; j<y; j++)
    for(int k=0; k<z; k++)
      a[i][j][k] = something;

free(a);
Run Code Online (Sandbox Code Playgroud)

编辑(下面文本中的任何讽刺语气都是故意的)

为了那些拒绝接受任何少于三级间接的解决方案的三星级程序员的利益,这里有一个如何正确进行三星级编程的示例。

不幸的是,它还不包含无条件向上分支、内存泄漏或复杂的指针算术。但对于一个三星级的程序员来说,这样快乐的事情当然是微不足道的事了。然而,它确实保证了数据缓存未命中,因此程序将以与没有任何数据缓存的系统相同的性能运行。

也可以考虑将分配的指针到指针到指针作为参数传递,从而获得4星!

[例如,指针到指针方法是非常糟糕的做法,但如果您出于未知原因坚持使用它,那么您最好正确使用它。]

#include <stdlib.h>
#include <stdio.h>


void free_int_3d (int*** ppp, size_t X, size_t Y, size_t Z)
{
  (void)Z;

  if(ppp == NULL)
  {
    return ;
  }

  for(size_t x=0; x < X; x++)
  {
    if(ppp[x] != NULL)
    {
      for(size_t y=0; y < Y; y++)
      {
        if(ppp[x][y] != NULL)
        {
          free(ppp[x][y]);
        }
      }
      free(ppp[x]);
    }
  }
  free(ppp);
}


#define malloc_with_cleanup(ptr, size)     \
ptr = malloc(size);                        \
if(ptr == NULL)                            \
{                                          \
  free_int_3d(result, X, Y, Z);            \
  return NULL;                             \
}

int*** int_alloc_3d (size_t X, size_t Y, size_t Z)
{
  int*** result = NULL;

  malloc_with_cleanup(result, sizeof(int**[X]));
  for(size_t x=0; x<X; x++)
  {
    malloc_with_cleanup(result[x], sizeof(int*[Y]));
    for(size_t y=0; y<Y; y++)
    {
      malloc_with_cleanup(result[x][y], sizeof(int[Z]));
    }
  }
  return result;
}


int main (void)
{
  const size_t X = 5;
  const size_t Y = 3;
  const size_t Z = 4;

  int*** ppp = int_alloc_3d(X, Y, Z);

  for(size_t i=0; i<X; i++)
  {
    for(size_t j=0; j<Y; j++)
    {
      for(size_t k=0; k<Z; k++)
      {
        ppp[i][j][k] = (int)k;
        printf("%d ", ppp[i][j][k]);
      }
      printf("\n");
    }
    printf("\n");
  }

  free_int_3d(ppp, X, Y, Z);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

0 1 2 3
0 1 2 3
0 1 2 3

0 1 2 3
0 1 2 3
0 1 2 3

0 1 2 3
0 1 2 3
0 1 2 3

0 1 2 3
0 1 2 3
0 1 2 3

0 1 2 3
0 1 2 3
0 1 2 3
Run Code Online (Sandbox Code Playgroud)