我有以下代码来动态创建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)
。
谢谢!
答案 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);