动态分配C中的数组数组

我并不真正理解C中的一些基本内容,比如动态分配数组数组。 我知道你可以这样做:

int **m; 

为了声明一个二维数组(随后将使用一些* alloc函数分配)。 也可以通过*(*(m + line) + column) “轻松”访问它。 但是我应该如何为该数组中的元素赋值? 使用gcc以下语句m[line][column] = 12; 因故障而失败。

任何文章/文档将不胜感激。 🙂

m[line][column] = 12语法正常(假设linecolumn在范围内)。

但是,您没有编写用于分配它的代码,因此很难确定它是错还是正确。 它应该是符合的

 m = (int**)malloc(nlines * sizeof(int*)); for(i = 0; i < nlines; i++) m[i] = (int*)malloc(ncolumns * sizeof(int)); 

一些旁注:

  • 这样,您可以为每条线分配不同的长度(例如,三角形arrays)
  • 稍后您可以在使用数组时realloc()或free()单个行
  • 当你释放()整个数组时,你必须释放()每一行

您的语法m [line] [colummn]是正确的。 但是为了在C中使用2D数组,必须为它分配内存。 例如,此代码将为给定行和列的表分配内存。

 int** AllocateArray(int line, int column) { int** pArray = (int**)malloc(line*sizeof(int*)); for ( int i = 0; i < line; i++ ) { pArray[i] = (int*)malloc(column*sizeof(int)); } return pArray; } 

注意,为了简洁起见,我省略了malloc的错误检查。 真正的解决方案应该包括它们。

它不是一个二维数组 – 它是一个数组数组 – 因此它需要多个分配。

这是quinmars解决方案的修改版本,它只分配一个内存块,并且可以通过void *提供通用值:

 #include  #include  #include  void ** array2d(size_t rows, size_t cols, size_t value_size) { size_t index_size = sizeof(void *) * rows; size_t store_size = value_size * rows * cols; char * a = malloc(index_size + store_size); if(!a) return NULL; memset(a + index_size, 0, store_size); for(size_t i = 0; i < rows; ++i) ((void **)a)[i] = a + index_size + i * cols * value_size; return (void **)a; } int printf(const char *, ...); int main() { int ** a = (int **)array2d(5, 5, sizeof(int)); assert(a); a[4][3] = 42; printf("%i\n", a[4][3]); free(a); return 0; } 

我不确定将void **int **是否真的安全(我认为标准允许在转换为void *时进行转换?),但它适用于gcc。 为了安全起见,你应该用int *替换每个出现的void * int * ...


以下宏实现了先前算法的类型安全版本:

 #define alloc_array2d(TYPE, ROWS, COLS) \ calloc(sizeof(TYPE *) * ROWS + sizeof(TYPE) * ROWS * COLS, 1) #define init_array2d(ARRAY, TYPE, ROWS, COLS) \ do { for(int i = 0; i < ROWS; ++i) \ ARRAY[i] = (TYPE *)(((char *)ARRAY) + sizeof(TYPE *) * ROWS + \ i * COLS * sizeof(TYPE)); } while(0) 

像这样使用它们:

 int ** a = alloc_array2d(int, 5, 5); init_array2d(a, int, 5, 5); a[4][3] = 42; 

虽然我同意其他答案,但在大多数情况下,一次分配整个数组会更好,因为malloc非常慢。

 int ** array_new(size_t rows, size_t cols) { int **array2d, **end, **cur; int *array; cur = array2d = malloc(rows * sizeof(int *)); if (!array2d) return NULL; array = malloc(rows * cols * sizeof(int)); if (!array) { free(array2d); return NULL; } end = array2d + rows; while (cur != end) { *cur = array; array += cols; cur++; } return array2d; } 

要释放数组,只需执行: free(*array); free(array); free(*array); free(array);

注意:此解决方案仅在您不想更改行的顺序时才有效,因为您可能会丢失第一个元素的地址,稍后需要释放该数组。

姆。 如何选择旧时尚烟雾和镜子?

 #define ROWS 5 #define COLS 13 #define X(R, C) *(p + ((R) * ROWS) + (C)) int main(void) { int *p = (int *) malloc (ROWS * COLS * sizeof(int)); if (p != NULL) { size_t r; size_t c; for (r = 0; r < ROWS; r++) { for (c = 0; c < COLS; c++) { X(r,c) = r * c; /* put some silly value in that position */ } } /* Then show the contents of the array */ for (r = 0; r < ROWS; r++) { printf("%d ", r); /* Show the row number */ for (c = 0; c < COLS; c++) { printf("%d", X(r,c)); } printf("\n"); } free(p); } else { /* issue some silly error message */ } return 0; } 

使用malloc(3)分配第一个数组并放入由malloc(3)创建的指针应该与array[r][c]因为它应该等效于*(*(array + r) + c) ,它符合C标准。