如何在C中初始化3D连续数组

我知道如何以下列方式执行一个不可能的非连续数组:

int main () { int ***array = (int***)malloc(3*sizeof(int**)); int i, j; for (i = 0; i < 3; i++) { // Assign to array[i], not *array[i] (that would dereference an uninitialized pointer) array[i] = (int**)malloc(3*sizeof(int*)); for (j = 0; j < 3; j++) { array[i][j] = (int*)malloc(3*sizeof(int)); } } array[1][2][1] = 10; return 0; } 

使用上面的代码,数组[0] [j]块可能不连续。 为了获得连续性,我觉得我们需要以这种方式使用malloc

 int* array = (int*)malloc(3*3*3*sizeof(int)); int** y = (int**)malloc(3*3*sizeof(int**)); int*** x = (int***)malloc(3*sizeof(int***)); for(i = 0; i < 3; i++) { vals = vals + i*m*n; x[i] = &vals; for(j = 0; j < 3; j++) { x[i][j] = vals + j * n; } } 

但是,我得到了地址分配的麻烦。 我不是程序员,任何人都可以纠正我的错吗? 提前致谢…

 int*** x = (int***)malloc(3*sizeof(int***)); 

应该

 int*** x = (int***)malloc(3*sizeof(int**)); 

现在初始化可以是:

  for(i = 0; i < 3; i++) { x[i] = y + 3*i; for(j = 0; j < 3; j++) { x[i][j] = array + i*3*3 + j*3; } } 

因此x[0]指向y的第一个元素, x[1]指向第四个,等等。而x[0][0] = y[0]指向array的第一个, x[0][1] = y[1]array的第四个等。

要分配连续的 3D数组,您只需执行以下操作(假设在编译时已知所有维度):

 #define D0 ... #define D1 ... #define D2 ... ... T (*arr)[D1][D2] = malloc( sizeof *arr * D0 ); // for any type T ... arr[i][j][k] = some_value(); ... 

arr被声明为指向D1 x D2数组的指针。 然后我们为D0这样的数组分配足够的空间( sizeof *arr == sizeof (T [D1][D2]) )。

使用此方法,arrays的所有内存都是连续分配的。 此外,您只需要一个电话即可释放全部内容。

如果直到运行时才知道维度, 并且您使用的是C99编译器或支持可变长度数组的C2011编译器,那么您仍然很幸运:

 size_t d0, d1, d2; ... T (*arr)[d1][d2] = malloc( sizeof *arr * d0 ); 

主要问题是如何将此作为参数传递给函数。 假设在编译时已知D1D2 ,如果您决定将其作为传递

 foo( arr, D0 ); 

那么foo的原型就需要了

 void foo( T (*aptr)[D1][D2], size_t n ) { ... aptr[i][j][k] = ...; } 

它只对n x D1 x D2大小的数组有用。

如果你去VLA路线,你需要声明尺寸并为它们传递值:

 void foo( size_t d0, size_t d1, size_t d2, T (*aptr)[d1][d2] ) // d1 and d2 *must* be // declared before aptr { ... arr[i][j][k] = some_value(); } void bar( void ) { size_t d0, d1, d2; ... T (*arr)[d1][d2] = malloc( sizeof *arr * d0 ); ... foo( d0, d1, d2, arr ); ... } 

如果您没有支持VLA的编译器,但仍希望连续分配此内存,则必须采用旧式路由 – 将其分配为1Darrays并手动计算偏移量:

 T *arr = malloc( sizeof *arr * d0 * d1 * d2 ); ... arr[i * d0 * d1 + j * d1 + k] = some_value(); 

我正在使用一些非常简洁的方法来分配带有行指针的多维数组。 函数multi_mallocmulti_free可用于任意维度和任意类型的数组,它们基本上适用于所有平台以及C和C ++

您可以递归地分配例如带有行指针的三维数组。 例如10x20x30维arrays

 float*** data = (float***) multi_malloc(sizeof(float),3, 10,20,20); 

访问元素,如

 data[2][3][4] = 2.0; 

并释放一切(数据和行指针)

 multi_free(data,3); 

标题,我认为应该是C的一部分

 #pragma once #include  #include  #include  #include  #if (defined(_MSC_VER) && defined(_WIN32)) // Note when used inside a namespace, the static is superfluous # define STATIC_INLINE_BEGIN static inline //__forceinline # define STATIC_INLINE_END #elif (defined(__GNUC__)) # define STATIC_INLINE_BEGIN static inline # if defined(__CYGWIN__) # define STATIC_INLINE_END # else # define STATIC_INLINE_END __attribute__ ((always_inline)) # endif #endif STATIC_INLINE_BEGIN void* multi_malloc(size_t s, size_t d, ...) STATIC_INLINE_END; STATIC_INLINE_BEGIN void multi_free(void *r, size_t d) STATIC_INLINE_END; /** * Allocate multi-dimensional array and establish row pointers * * @param s size of each element * @param d number of dimension * * @return */ STATIC_INLINE_BEGIN void* multi_malloc(size_t s, size_t d, ...) { char* tree; va_list ap; /* varargs list traverser */ size_t max, /* size of array to be declared */ *q; /* pointer to dimension list */ char **r, /* pointer to beginning of the array of the * pointers for a dimension */ **s1, *t; /* base pointer to beginning of first array */ size_t i, j; /* loop counters */ size_t *d1; /* dimension list */ va_start(ap,d); d1 = (size_t *) malloc(d*sizeof(size_t)); for(i=0;i 

您可以为每个项目是二维数组的项目缓冲区分配内存。 所以它实际上是一个三维数组:

 #include  #include  #include  #define N 3 int main() { int (*array)[N][N] = malloc(N * N * N * sizeof(int)); /* set 0 to all values */ memset(array, 0, N * N * N * sizeof(int)); /* use as 3D array */ array[0][0][0] = 1; array[1][1][1] = 2; array[2][2][2] = 3; int i; /* print array as contiguous buffer */ for (i = 0; i < N * N * N; ++i) printf("i: %d\n", ((int*) array)[i]); free(array); return 0; } 

因此,在内存中, array被放置为常规int array[N][N][N]

虽然我认为在堆栈上创建的普通数组最好:

 int array[3][3][3];//can avoid a lot of free() calls later on 

这是一种动态创建3D数组的方法:
(我在这里使用calloc而不是malloc,因为它创建了初始化的内存空间)

 int *** Create3D(int p, int c, int r) { int ***arr; int x,y; arr = calloc(p, sizeof(arr)); //memory for int for(x = 0; x < p; x++) { arr[x] = calloc(c ,sizeof(arr)); //memory for pointers for(y = 0; y < c; y++) { arr[x][y] = calloc(r, sizeof(int)); } } return arr; } 

用法可能是:

 int ***array = Create3D(3,3,3); for(i=0;i<3;i++) for(j=0;j<3;j++) for(k=0;k<3;k++) array[i][j][k] = (i+1)*(j+1)*(k+1); 

请注意,在此示例中不会返回[c] [m] [re] alloc()的返回值。 虽然在C中没有严格禁止,但不建议这样做。 (在C ++中不是这种情况,需要它)
请记住 ,必须释放所有已分配的内容。 注意释放按分配的相反顺序完成:

 void free3D(int ***arr, int p, int c) { int i,j; for(i=0;i 

用法可能是:

 free3D(array,3,3);