C动态3D阵列存储器

时间:2017-11-21 08:37:54

标签: c arrays dynamic

我有以下代码来动态创建2D数组。对于我的应用程序,我需要连续存储数据。

我想将下面的2D代码推广到3D数组。我怎么能这样做?

double *psiMemLoc;
double **psi;

  psiMemLoc = malloc(sizeof(double)*(lasty-firsty+3)*(lastx-firstx+3));
  psi = malloc(sizeof(double *) * (lasty-firsty+3));
  for(j=firsty-1; j<=lasty+1; j++){
    psi[j] = psiMemLoc + (lastx-firstx+3)*j;
  }

使用上面的代码,我可以像psi一样访问psi[j][i]的元素。为了重申我的目标,我想生成一个可以使用psi[k][j][i]访问的3D数组。

为了给出一些上下文,我正在解决2D PDE,第三个维度将用于存储一些以前的时间步骤解决方案。因此,时间步之间的内存位置数应为(lasty-firsty+3)*(lastx-firstx+3)

谢谢!

3 个答案:

答案 0 :(得分:3)

您可以像这样获得3d连续分配的内存

double (*a)[sz][sz]= malloc(sizeof *a *sz);
if( a == NULL){
   // error in malloc
   exit(1);
}

这与你所做的有点不同。但它会满足你的目的。

  for(size_t i=0;i<sz;i++)
    for(size_t j=0;j<sz;j++)
      for(size_t k=0;k<sz;k++)
         // access a[i][j][k]

免费只是一个像free(a)这样的电话。 (当你完成它时,释放内存)。

注意:这适用于C99及以后。除了C11使VLA的选择性打破了保证。但作为一种出路,您总是可以分配整个块并相应地访问它们。

另一种方法是使用锯齿状数组(不是连续的内存)。

double ***a;

现在在某些功能中你可以这样做

a = malloc(sizeof *a* sz1);
if( a == NULL ){
   // ..
}
for(size_t i = 0; i<sz1; i++){
 a[i]= malloc(sizeof *a[i]*sz2);
 if( !a[i] ){
   for(size_t j = 0; j<sz2; j++)
     a[i][j]=malloc(sizeof *a[i][j]*sz3);
     if( a[i][j] == NULL){
      //error
     }
 }
 else
   // error
}
//If you have an jagged array a[sz1][sz2][sz3];

答案 1 :(得分:1)

这是一个补充答案:使用malloc()分配多维数组的正确方法确实是使用VLA语法,如coderredoc's answer所示。不幸的是,C11不再需要符合标准的实现来支持VLA。虽然这应该几乎从不在实践中成为一个问题,但仍然值得注意的是,您可以在不使用VLA的情况下在代码中明确地执行相同操作:

int x = 5;
int y = 10;
int z = 3;

double *array3d = malloc(x*y*z * sizeof *array3d);

// access to [3][2][1]:
array3d[3*y*z + 2*z + 1]

虽然这不是一个真正的3d数组,但它具有相同的内存表示(连续),您只需显式执行索引计算,否则将由编译器生成。

由于代码的可读性较低,如果可以的话,总是更喜欢其他答案中显示的语法( - >如果您的编译器支持VLA,并且没有理由认为它曾经编译过一个那不是。

答案 2 :(得分:0)

根本看起来不像2D / 3D阵列。

你创建的是一个指针数组,每个指针指向一个连续的内存块。虽然这可能会给人一种指针的感觉,但制作2D数组的正确方法是 -

double (*array_2d)[lastx-firstx+3] = malloc(sizeof (*array_2d) * (lasty-firsty+3));

类似地,可以将3D阵列设为 -

double (*array_3d)[X][Y] = malloc(sizeof(*array_3d) * Z);