我想创建一个指向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浮点数组,然后整个阵列???
答案 0 :(得分:4)
如果你在编译时知道数组大小(如果你知道SIZE
是编译时常量),你应该只声明一个二维数组。你根本不需要释放它(但绝不能)。
float array1[SIZE][3];
只有在编译时不知道维度时,才需要使用calloc
并创建指针数组。在这种情况下,每次拨打free
都应该拨打一次calloc
。由于您在释放数组后无法使用数组,因此需要在释放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));
那是因为 columns 的数量在编译时是已知的,并且这是所有指针算术需要知道的。然后你可以写array1[i][j]
这样的东西,你仍然可以传递array1[i]
,好像它是一个真正的指针。 C很棒,利用它!
答案 1 :(得分:2)
我想创建一个指向3个浮点数组的指针数组。这样做的正确方法是什么?
为什么要array of pointers to arrays
? array 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);
然后,您需要为每个free
执行malloc
,如
// free the individual arrays
for (int i = 0; i < SIZE; i++)
free(arr[i]);
// free the array of arrays
free(arr);
这里要取消的教训是避免将数组全部动态分配。坚持使用std::vector
或堆栈分配的数组。
答案 2 :(得分:2)
一般规则是,每次拨打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;
}
当然用适当的变量替换定义。
通过这样做,您将: