我相信这段代码会强制3维数组的内存分配是连续的。
void ***calloc_3d_array(size_t n3, size_t n2, size_t n1, size_t size){
void ***array;
size_t i, j;
if ((array = (void***)calloc(n3, sizeof(void**))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 1st-pointers\n",
(int)n3);
return NULL;
}
if ((array[0] = (void**)calloc(n3*n2, sizeof(void*))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 2nd-pointers\n",
(int)(n3*n2));
free((void*)array);
return NULL;
}
for (i=1; i<n3; i++) {
array[i] = (void**)((unsigned char*)array[0]+i*n2*sizeof(void*));
}
if ((array[0][0] = (void*)calloc(n3*n2*n1, size)) == NULL) {
printf("[calloc_3d] failed to alloc. memory (%d X %d X %d of size %d)\n",
(int)n3, (int)n2, (int)n1, (int)size);
free((void*)array[0]);
free((void*)array);
return NULL;
}
for (j=1; j<n2; j++) {
array[0][j] = (void**)((unsigned char*)array[0][j-1]+n1*size);
}
for (i = 1; i < n3; i++) {
array[i][0] = (void**)((unsigned char*)array[i-1][0]+n2*n1*size);
for (j = 1; j < n2; j++) {
array[i][j] = (void**)((unsigned char*)array[i][j-1]+n1*size);
}
}
return array;
}
我试图将其更改为一个连续分配4维数组的函数。我不完全理解3D情况是否完美无缺,因此抽象到第4维有点不稳定。我几乎不确定到底为什么在任何循环中3d代码中都有array [i] =(void **)或array [i] [j] =(void **),所以在4d代码中我拥有所有数组[i] [j] [k] =(void ***)。这是我目前拥有的
void ****calloc_4d_array(size_t n4, size_t n3, size_t n2, size_t n1, size_t size){
void ****array;
size_t i, j, k;
/* Alloc array of 3d pointers */
if ((array = (void****)calloc(n4, sizeof(void***))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 1st-pointers\n",
(int)n4);
return NULL;
}
/* In first slot allocate a entire 2d pointer array */
if ((array[0] = (void***)calloc(n4*n3, sizeof(void**))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 2nd-pointers\n",
(int)(n4*n3));
free((void*)array);
return NULL;
}
/* Loop over slots and adjust address to accommodate 2d pointers */
for (i = 1; i < n4; i++) {
array[i] = (void***)((unsigned char*)array[0]+i*n3*sizeof(void**));
}
/* In the first 2d pointer, allocate the entire space for 1d pointers*/
if ((array[0][0] = (void**)calloc(n4*n3*n2, sizeof(void*))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 3rd-pointers\n",
(int)(n4*n3*n2));
free((void*)array[0]);
free((void*)array);
return NULL;
}
/* Loop over other 2d slots and adjust address to accommodate type */
for (j=1; j<n3; j++) {
array[0][j] = (void**)((unsigned char*)array[0][j-1]+n2*size);
}
for (i=1; i<n4; i++) {
array[i][0] = (void**)((unsigned char*)array[i-1][0]+n3*n2*size);
for (j=1; j<n3; j++) {
array[i][j] = (void**)((unsigned char*)array[i][j-1]+n2*size);
}
}
/* Finally allocate for entire array */
if ((array[0][0][0] = (void*)calloc(n4*n3*n2*n1, size)) == NULL) {
printf("[calloc_3d] failed to alloc. memory (%d X %d X %d X %d of size %d)\n",
(int)n4, (int)n3, (int)n2, (int) n1, (int)size);
free((void*)array[0][0]);
free((void*)array[0]);
free((void*)array);
return NULL;
}
for (k=1; k<n2; k++) {
array[0][0][k] = (void***)((unsigned char*)array[0][0][k-1]+n1*size);
}
for (j=1; j<n3; j++) {
array[0][j][0] = (void***)((unsigned char*)array[0][j-1][0]+n2*n1*size);
for (k=1; k<n2; k++) {
array[0][j][k] = (void***)((unsigned char*)array[0][j][k-1]+n1*size);
}
}
for(i=1; i<n4; i++) {
array[i][0][0] = (void***)((unsigned char*)array[i-1][0][0]+n3*n2*n1*size);
for (j=1; j<n3; j++) {
array[i][j][0] = (void***)((unsigned char*)array[i][j-1][0]+n2*n1*size);
for (k=1; k<n2; k++) {
array[i][j][k] = (void***)((unsigned char*)array[i][j][k-1]+n1*size);
}
}
}
return array;
}
编辑:编译器向我发出了有关我的(void ***)问题的警告,并且array [] []是(void **)似乎很有意义,但是我仍然不知道为什么对array [i] =(void ***)而不是array [i] =(void *)很满意。换句话说,为什么用calloc array[0][0][0] = (void*)calloc(n4*n3*n2*n1, size)
它(void *),但是使用位移/设置地址(?)array[0][0][k] = (void***)((unsigned char*)array[0][0][k-1]+n1*size);
时为什么(void ***)?我想无论哪种对象array [] [] []都是(void *)或(void ***)。
答案 0 :(得分:0)
这应该分配2个及以上维度数组,并连续使用递归。建议将FORTRAN用于此类高维计算,这不是高效的内存。该示例似乎是valgrind clean。
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void *alloc_nd(int *dim, int nd, size_t size)
{
assert(nd>=2);
void **p = malloc(sizeof(void*)*dim[0]);
if(nd==2) {
p[0] = malloc(size*dim[0]*dim[1]);
for(int i=1; i<dim[0]; i++)
p[i] = p[i-1]+size*dim[1];
} else {
int xd[nd-1];
for(int i=1; i<nd; i++)
xd[i-1] = dim[i];
xd[0] *= dim[0]; //callapse the 1st two dimension
p[0] = alloc_nd(xd, nd-1, size);
for(int i=1; i<dim[0]; i++)
p[i] = p[i-1]+sizeof(void*)*dim[1];
}
return p;
}
void free_nd(void *p, int nd)
{
if(nd==2) {
free(((void**)p)[0]);
free(p);
} else {
free_nd(((void**)p)[0], nd-1);
free(p);
}
}
int main()
{
int dim[] = {3,4,5,6};
int ****array;
array = (int****)alloc_nd(dim, 4, sizeof(int));
for(int i0=0; i0<dim[0]; i0++)
for(int i1=0; i1<dim[1]; i1++)
for(int i2=0; i2<dim[2]; i2++)
for(int i3=0; i3<dim[3]; i3++)
array[i0][i1][i2][i3] = i0+i1+i2+i3;
int *p = &array[0][0][0][0]; //do you mean continuous in this way?
for(int i=0; i<dim[0]*dim[1]*dim[2]*dim[3]; i++)
printf("p[%5d]=%d\n", i, p[i]);
free_nd(array, 4);
return 0;
}