在Heap中用C(不是指针数组)分配2D数组

时间:2015-05-23 21:16:45

标签: c arrays pointers memory-management allocation

我有一个简单的问题,但答案似乎很难找到:

如何在C(非C ++)中创建一个真正的2D数组,动态调整大小(编译时未知的大小),而不是堆上的指针数组,以便我可以将该分配放入单独的函数中并返回已分配的数组,而不接收gcc -Wall的任何警告?

我在SO和其他论坛上发现了很多其他问题,但答案都有一些缺陷:

  • 我看到了许多答案,其中展示了如何初始化一个指针数组,根据一些注释可能会导致内存碎片,并且在不再使用时需要释放一个循环。
  • 我不想只拥有预定义的数组大小,但想在某些循环中使用它,创建多种大小的数组。
  • 我也不希望预定义数组中的值,而是在程序运行时重新计算它们。
  • 我读到了内存中的布局,当使用一些创建数组的方法时可能会有所不同,而人们仍然可以使用这样的数组:a[y][x]。我希望我的数组也有一个真正的2D数组的内存布局。

实现这种真正2D阵列分配的正确方法是什么?

修改#1: 分配方法的返回类型可以是指向已分配数组的指针。

2 个答案:

答案 0 :(得分:5)

您不需要特殊功能。就这样做吧

double (*A)[n][m] = malloc(sizeof *A);

从C99开始,nm可以是您想要的任何正整数表达式。

这样的东西是指向VLA,可变长度数组的指针。

答案 1 :(得分:1)

我知道这不是完美的答案;但我希望它会有所帮助。

#include <stdio.h>
#include <stdlib.h>
#define ELEM(myArr,X,Y) (myArr->arr[myArr->cols * X + Y])
#define FREE_MY_ARR(myArr) \
    if(myArr){if(myArr->arr) free(myArr->arr);  free(myArr);}
    typedef struct myArr
    {
        int rows , cols;
        int * arr;
    } myArr;

    myArr * create_my_arr(int rows , int cols)
    {
        myArr * my_arr = malloc(sizeof(myArr));
        my_arr->rows =rows;
        my_arr->cols=cols;
        my_arr->arr= malloc(rows * cols * sizeof(*my_arr->arr));
        return my_arr;
    }

    int main()
    {
        int rows = 4 , cols = 5;
        myArr * my_arr = create_my_arr(4,5);
        int i , j ;
        for(i = 0 ; i < rows;i++)
            for(j = 0 ; j < cols;j++)
            {
                ELEM(my_arr , i , j) = cols * i + j; // 0,1,2,3,4,5,6,7,8,...etc
            }
        //print array.
        for(i = 0 ; i < rows;i++)
        {
            for(j = 0 ; j < cols;j++)
            {
                printf("arr[%d,%d]=%d\t" , i , j , ELEM(my_arr ,i , j));
            }
        printf("\n");
        }
        FREE_MY_ARR(my_arr);
       return 0;
    }

输出:

   gcc -o s s.c &&s
    arr[0,0]=0      arr[0,1]=1      arr[0,2]=2      arr[0,3]=3      arr[0,4]=4
    arr[1,0]=5      arr[1,1]=6      arr[1,2]=7      arr[1,3]=8      arr[1,4]=9
    arr[2,0]=10     arr[2,1]=11     arr[2,2]=12     arr[2,3]=13     arr[2,4]=14
    arr[3,0]=15     arr[3,1]=16     arr[3,2]=17     arr[3,3]=18     arr[3,4]=19