繁体   English   中英

在 C 中动态分配数组的函数——两者之间有什么区别吗?

[英]Functions for dynamically allocating an array in C -- Any difference between the two?

假设您在 C 中有一个函数,它接受二维数组的维数(为简单起见,比如说一个正方形 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 - 向函数添加 in-out 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...
}

显然,它们返回相同的结果并完成相同的任务,但是否认为一种比另一种更安全/更有效/更好的做法? 在我看来,第二个变体只是让事情看起来有点多余,但我很好奇两者之间是否有任何真正的区别以及调用它们时堆栈/堆上会发生什么。 希望这不是一个愚蠢的问题; 这只是我一直很好奇的事情。 如果有人有见解可以分享,我将不胜感激。

我可能会尽量避免多次调用mallocfree ,所以这种方法就是我要做的:

示例 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 ROW\n");
        exit(1);
    }

    printf("Give the COL: ");
    if ( scanf("%u",&col) != 1){
        printf("Error, scanf COL\n");
        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, malloc\n");
        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 ROW\n");
        exit(1);
    }

    printf("Give the COL: ");
    if ( scanf("%zu",&col) != 1){
        printf("Error, scanf COL\n");
        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, malloc\n");
        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

这里的重点是在两个例子中mallocfree的调用只发生一次

IMO,在这两者中,您最好简单地返回值。 这样你和来电者之间就有了一道纯粹而坚固的墙。

“给我一些东西!”

“好的,这里有一些东西。”

另一方面,为了实际分配一个固定大小的数组,为什么要使用指针呢? 为什么不声明您的返回类型以便可转换为一个大小的数组?

int (*p2a)[15] = (int(*)[15])create_array_2(15, 15);

然后你会calloc(15*15,sizeof(int))并完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM