18

如何在函数中为二维数组分配动态内存?我试过这样:

int main()
{
  int m=4,n=3;
  int** arr;
  allocate_mem(&arr,n,m);
}


void allocate_mem(int*** arr,int n, int m)
{
  *arr=(int**)malloc(n*sizeof(int*));
  for(int i=0;i<n;i++)
    *arr[i]=(int*)malloc(m*sizeof(int));
} 

但它不起作用。

4

8 回答 8

33

您的代码是错误的,*arr[i]=(int*)malloc(m*sizeof(int));因为运算符的优先[]高于*尊重运算符:在表达式*arr[i]中,首先arr[i]评估然后*应用。您需要的是相反的(取消引用arr,然后应用[])。

像这样使用括号:(*arr)[i]覆盖运算符优先级。现在,您的代码应如下所示:

void allocate_mem(int*** arr, int n, int m)
{
  *arr = (int**)malloc(n*sizeof(int*));
  for(int i=0; i<n; i++)
    (*arr)[i] = (int*)malloc(m*sizeof(int));
} 

要进一步了解上述代码中发生的情况,请阅读此答案

重要的是,一旦你完成了动态分配的内存,你总是显式地释放它。要释放上述函数分配的内存,您应该这样做:

void deallocate_mem(int*** arr, int n){
    for (int i = 0; i < n; i++)
        free((*arr)[i]);
    free(*arr); 
}

此外,创建 2D 数组的更好方法是使用单个函数调用分配连续内存,如下所示:malloc()

int* allocate_mem(int*** arr, int n, int m)
{
  *arr = (int**)malloc(n * sizeof(int*));
  int *arr_data = malloc( n * m * sizeof(int));
  for(int i=0; i<n; i++)
     (*arr)[i] = arr_data + i * m ;
  return arr_data; //free point
} 

要释放此内存:

void deallocate_mem(int*** arr, int* arr_data){
    free(arr_data);
    free(*arr);
}

请注意,在第二种技术中 malloc 仅被调用两次,因此在释放代码中 free 仅被调用两次,而不是在循环中调用它。所以这个技术应该更好。

于 2013-02-25T08:21:56.107 回答
4

考虑一下:只是单一分配

int** allocate2D(int m, int n)
{
    int **a = (int **)malloc(m * sizeof(int *) + (m * n * sizeof(int)));

    int *mem = (int *)(a + m);

    for(int i = 0; i < m; i++)
    {
        a[i] = mem + (i * n);
    }

    return a;
}

免费:

free(a);
于 2013-10-20T01:13:47.043 回答
3

如果您的数组不需要调整大小(好吧,您可以,但 il 会更复杂一点),有一种更简单/更有效的方法可以在 C 中构建 2D 数组。

看看http://c-faq.com/aryptr/dynmuldimary.html

第二种方法(对于名为 array2 的数组)非常简单,不那么痛苦(尝试添加对 malloc 的返回值的测试),并且更有效。

我刚刚对它进行了基准测试,对于 200x100 数组,分配和释放 100000 次:

  • 方法一:1.8s
  • 方法二:47ms

并且数组中的数据将更加连续,这可能会加快速度(您可能会获得一些更有效的技术来复制、重置......以这种方式分配的数组)。

于 2013-02-25T12:36:09.963 回答
2

与其将内存分配在许多不同的块中,不如将其分配在连续的内存块中。请执行下列操作:

int** my2DAllocation(int rows,int columns)
{
   int i;
   int header= rows *sizeof(int *);
   int data=rows*cols*sizeof(int);
   int ** rowptr=(int **)malloc(header+data);
   if(rowptr==NULL)
   {
      return NULL:
   }
   int * buf=(int*)(rowptr+rows);
   for(i=0;i<rows;i++)
   {
      rowptr[i]=buf+i*cols;
   } 
   return rowptr;
}
于 2014-07-19T17:25:15.637 回答
1

这是为数组分配空间的一种不必要的复杂方式。考虑这个成语:

int main(void) {
    size_t m = 4, n = 3;
    int (*array)[m];
    array = malloc(n * sizeof *array);
    free(array);
}
于 2013-02-25T09:22:52.757 回答
0

我尝试使用以下代码将内存分配给二维数组。

    #include<stdio.h>
    #include<malloc.h>
    void main(void)
    {
    int **p;//double pointer holding a 2d array
    int i,j;
    for(i=0;i<3;i++)
    {
    p=(int**)(malloc(sizeof(int*)));//memory allocation for double pointer
    for(j=(3*i+1);j<(3*i+4);j++)
    {
    *p = (int*)(malloc(sizeof(int)));//memory allocation for pointer holding integer array
    **p = j;                  
    printf(" %d",**p);//print integers in a row 
    printf("\n");
    p++;
    }
    }
    }

上述代码的输出是:-

1 2 3

4 5 6

7 8 9

为了从指针的角度理解二维数组,我们需要了解它将如何在内存中分配,它应该是这样的:-

                1    2    3
    1000 -->   100  104  108

                4    5    6
    1004 -->   200  204  208

                7    8    9
    1008 -->   300  304  308 

由上可知,当我们为双指针指针p分配内存时,它指向的是一个整数数组,所以在这个例子中,我们看到0x1000就是指针p。

该指针指向整数指针 *p,它是整数数组,当内存在内部 for 循环内分配时,在第一次迭代期间,当我们分配 **p = j 时,指针是指向整数值 1 的 0x100。同样,它将在循环的下一次迭代中指向 2 和 3。

在外循环的下一次迭代之前,双指针递增,在下一次迭代内,如本例所示,指针现在位于 0x1004 并指向整数指针,它是整数数组 4,5,6 和类似用于循环中的下一次迭代。

于 2014-03-26T16:57:31.747 回答
-1

试试下面的代码:

 void allocate_mem(int*** arr,int n, int m)
{
  *arr=(int**)malloc(n*sizeof(int*));
  for(int i=0;i<n;i++)
    *(arr+i)=(int*)malloc(m*sizeof(int));
} 
于 2016-08-24T11:20:16.793 回答
-1

2d Array 使用 malloc 动态排列:

int row = 4;
int column = 4;
int val = 2;
// memory allocation using malloc   

int **arrM = (int**)malloc (row*sizeof(int*));

for (int i=0;i<row;i++)
{
    arrM[i] = (int*)malloc(column*sizeof(int));
    // insert the value for each field
    for (int j =0;j<column;j++,val++)
    {
      arrM[i][j]     = val;
    }
}

// De-allocation

for (int i=0;i<row;i++)
{
    free(arrM[i]);
}
free(arrM);
arrM = 0;

//
// Now using New operator:
//

int **arr = new int*[row];
int k = 1;
for (int i=0;i<row;i++)
{
    arr[i] = new int[column];
    // insert the value for each field
    for (int j =0;j<column;j++,k++)
    {
      arr[i][j]  = k;
    }
}
cout<<"array value is = "<<*(*(arr+0)+0)<<endl;
cout<<"array value is = "<<*(*(arr+3)+2)<<endl;

// Need to deallcate memory;

for (int i=0;i<row;i++)
{
delete [] arr[i];
}
delete []arr;
arr = 0;
于 2017-01-10T16:34:46.913 回答