[英]Contiguous memory for multidimensional array
我相信這段代碼會強制3D數組的內存分配是連續的。
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][0] = (void*)calloc(n4*n3*n2*n1, size)
,但是在使用位移/設置地址(?) array[0][0][k] = (void***)((unsigned char*)array[0][0][k-1]+n1*size);
? 我認為無論哪種對象array [] [] []都是(void *)或(void ***)。
這應該分配2個及以上維度數組,並連續使用遞歸。 建議將FORTRAN用於此類高維計算,這不是高效的內存。 該示例似乎valgrind很干凈。
#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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.