假设你在C中有一个函数,它接受2d数组的维度(为了简单起见,比如正方形的nxn数组),动态分配数组,然后返回它。
我知道在这里分配内存一开始可能会被认为是一种不好的做法,因为它需要在其他地方释放,但假设这不是一个大问题。我想知道上述功能的这两种变体是否有任何优点/缺点:
变体1-在函数中本地定义int**变量,分配/返回数组:
int **create_array(int n) {
// define array pointer, allocate array...
int **a_ = (int**)calloc(n,sizeof(int*));
for (int i = 0; i < n; i++)
a_[i] = (int*)calloc(n,sizeof(int));
return a_;
}
int main() {
int n = 3;
int **array2d = create_array(n)
printf("First element: %d%c",array2d[0][0],'n');
// do stuff... etc...
}
变体2-将int**参数添加到函数,分配/返回数组:
int **create_array_2(int **a_, int n) {
// allocate array...
a_ = (int**)calloc(n,sizeof(int*));
for (int i = 0; i < n; i++)
a_[i] = (int*)calloc(n,sizeof(int));
return a_;
}
int main() {
int n = 3;
int **array2d;
array2d = create_array_2(array2d,n);
printf("First element: %d%c",array2d[0][0],'n');
// do other stuff... etc...
}
显然,他们得到了相同的结果,完成了相同的任务,但其中一个被认为比另一个更安全/更有效率/更好的实践吗?在我看来,第二个变体只是让事情看起来有点多余,但我很好奇这两者之间是否有真正的区别,以及调用它们时堆栈/堆上会发生什么。希望这不是一个愚蠢的问题;这只是我一直好奇的事情。如果有人有真知灼见可以分享,我将不胜感激。
我可能会尽量避免多次调用malloc
和free
,所以我将采用这种方法:
示例1:
#include <stdio.h>
#include <stdlib.h>
int *foo(size_t row, size_t col);
int main(void){
int *arr;
unsigned int row, col, k;
printf("Give the ROW: ");
if ( scanf("%u",&row) != 1){
printf("Error, scanf ROWn");
exit(1);
}
printf("Give the COL: ");
if ( scanf("%u",&col) != 1){
printf("Error, scanf COLn");
exit(2);
}
arr = foo(row, col);
for (k = 0 ; k < (row * col) ; k++){
printf("%d ",arr[k]);
}
free(arr);
}
int *foo(size_t row, size_t col){
unsigned int i, j;
int *arr = malloc(sizeof *arr * row * col);
int l = 0;
if(arr == NULL){
printf("Error, mallocn");
exit(3);
}
for ( i = 0; i < row ; i++){
for ( j = 0 ; j < col ; j++){
arr[i * col + j] = l;
l++;
}
}
return arr;
}
输出:
Give the ROW: 6
Give the COL: 3
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
示例2(如果您使用的是标准C):
#include <stdio.h>
#include <stdlib.h>
int (*foo(size_t row, size_t col))[];
int main(void){
size_t row, col;
printf("Give the ROW: ");
if ( scanf("%zu",&row) != 1){
printf("Error, scanf ROWn");
exit(1);
}
printf("Give the COL: ");
if ( scanf("%zu",&col) != 1){
printf("Error, scanf COLn");
exit(2);
}
int (*arr)[col] = foo(row, col);
for ( size_t i = 0; i < row; i++){
for( size_t j = 0; j < col; j++){
printf("%d ",*(*(arr+i)+j));
}
}
free(arr);
}
int (*foo(size_t row, size_t col))[]{
int (*arr)[col] = malloc(row * col * sizeof(int));
int l=0;
if (arr == NULL){
printf("Error, mallocn");
exit(3);
}
for ( size_t i = 0; i < row; i++){
for( size_t j = 0; j < col; j++){
*(*(arr+i)+j) = l;
l++;
}
}
return arr;
}
输出:
Give the ROW: 6
Give the COL: 3
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
这里的重点是,两个例子中的malloc
和free
的调用只发生一次
IMO,在这两者中,您最好简单地返回值。这样,在你和打电话的人之间就有了一堵纯净而坚固的墙。
"给我一些东西">
"好吧,这里有一些东西">
另一方面,对于实际分配固定大小的数组,为什么要使用指针呢?为什么不声明您的返回类型,以便可转换为一个大小合适的数组呢?
int (*p2a)[15] = (int(*)[15])create_array_2(15, 15);
然后你就calloc(15*15,sizeof(int))
了。