正确的方法来分配和释放指向数组的指针

我想创建一个指向3个浮点数组的指针数组。 这样做的正确方法是什么?

float *array1[SIZE]; // I think it is automatically allocated // OR float **array1 = calloc(SIZE, sizeof(float*)); free(array1); for (int i = 0; i < SIZE; i++) { array1[i] = (float[]){0,0,0}; // OR array1[i] = calloc(3, sizeof(float)); } 

那么我将如何释放数据呢? 我很确定只有free(array1); 不会工作,所以我会释放数组中的每个指针然后释放数组,或者因为我分配了三个浮点数,我会释放每个浮点数,然后每个3浮点数组,然后整个数组???

一般规则是, 每次调用malloc()calloc() ,都需要对返回的指针执行free()调用

如果你想要一个编译时已知大小的二维数组,只需使用二维数组! float val[5][3]完全有效。

如果你想要一个二维数组并且在编译时你不知道它的大小,你很可能想要使用一个标准的,单个的dieca()和一个合适的getter。

 #define ARR_COLUMNS 10 #define ARR_ROWS 10 float* arr = calloc (ARR_COLUMNS * ARR_ROWS, sizeof(float)); int get(float* arr, int x, int y) { if (x<0 || x>= ARR_COLUMNS) return 0; if (y<0 || y>= ARR_ROWS) return 0; return arr[ARR_COLUMNS*y+x]; } void set (int* arr, int x, int y, float val) { if (x<0 || x>= ARR_COLUMNS) return; if (y<0 || y>= ARR_ROWS) return; arr[ARR_COLUMNS*y+x] = val; } 

当然用适当的变量替换定义。

通过这样做,您将:

  • 节省自己昂贵的分配和释放
  • 内存碎片少
  • 简化您可能的realloc调用
  • 确保在没有常见[x] [y] vs [y] [x]迭代缓存问题的情况下更好地缓存数据并进行访问。

如果你在编译时知道数组大小(如果你知道,如果SIZE是编译时常量),你应该只声明一个二维数组。 您根本不需要释放它(也不能)。

 float array1[SIZE][3]; 

只有在编译时不知道维度时,才需要使用calloc并创建指针数组。 在这种情况下,每次调用calloc都应该有一个free的调用。 并且由于在释放数组后无法使用数组,因此在释放array1之前需要释放行数组。

 float **array1 = calloc(nrows, sizeof (float *)); for (int i=0; i < nrows; i++) array1[i] = calloc(3, sizeof(float)); // Use it... // Now free it for (int i=0; i < nrows; i++) free(array1[i]); free(array1); 

编辑:如果您不重新排列指针(例如,为了对行进行排序),您可以只使用一个calloc (以及之后的一次free调用)来完成所有这些操作:

 float (*array1)[3] = calloc(3*nrows, sizeof (float)); 

这是因为数在编译时是已知的,这是所有指针算术需要知道的。 然后你可以编写像array1[i][j]这样的东西,你仍然可以传递array1[i] ,好像它是一个指向行的真实指针。 C很棒,利用它!

我想创建一个指向3个浮点数组的指针数组。 这样做的正确方法是什么?

为什么要一个array of pointers to arraysarray of arrays不足够吗? (请记住,数组已经是指针式的,它们不是通过值传递的,而是当数组作为参数传递给函数时传递第一个元素的地址)。

 // stack allocation, no need to free float array[SIZE][3]; for (int i = 0; i < SIZE; i++) { // do something with array[i][0], array[i][1], array[i][2] } 

那么我将如何释放数据呢?

在这种情况下,您不会,因为数据是堆栈分配的(一旦超出范围将自动清理)。 请记住,经验法则是,对于您所做的每个内存分配,都需要相应的空闲。 因此,如果为浮点数组分配内存,就像在

 float* arr = malloc(sizeof(float) * 3); // array of 3 floats 

然后你只需要在malloc'd的数组上自由调用,不需要释放单独的浮点数。 如果您执行嵌套分配,请执行

 // array of length SIZE, consisting of float pointers float** arr = malloc(sizeof(float*) * SIZE); // allocate the array of 3 floats at each index for (int i = 0; i < SIZE; i++) arr[i] = malloc(sizeof(float) * 3); 

然后你需要为每个malloc执行一个free的,就像在

 // free the individual arrays for (int i = 0; i < SIZE; i++) free(arr[i]); // free the array of arrays free(arr); 

这里要取消的教训是避免将数组全部动态分配。 坚持使用std::vector或堆栈分配的数组。