【问题标题】:Allocate memory 2d array in function C在函数 C 中分配内存二维数组
【发布时间】:2013-02-10 08:17:50
【问题描述】:

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

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));
} 

但它不起作用。

【问题讨论】:

标签: c arrays function 2d allocation


【解决方案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;

【讨论】:

    【解决方案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;
    }
    

    【讨论】:

      【解决方案3】:

      您的代码在*arr[i]=(int*)malloc(m*sizeof(int)); 处出错,因为[] 运算符的precedence 高于* 尊重运算符:在表达式*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));
      } 
      

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

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

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

      此外,创建二维数组的更好方法是使用单个 malloc() 函数调用 allocate contiguous memory,如下所示:

      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 仅被调用两次,而不是在循环中调用它。所以这个技术应该会更好。

      【讨论】:

      • @user2089491 如果它解决了您的问题,请点击左侧的“复选标记”,将其视为正确答案。
      【解决方案4】:

      试试下面的代码:

       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));
      } 
      

      【讨论】:

        【解决方案5】:

        我已经尝试了以下代码来为二维数组分配内存。

            #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循环中分配时,在第一次迭代期间指针是0x100,它指向整数值1,当我们分配**p = j.同样,它将在循环的下一次迭代中指向 2 和 3。

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

        【讨论】:

          【解决方案6】:

          考虑一下:只是单一分配

          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);
          

          【讨论】:

            【解决方案7】:

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

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

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

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

            • 方法一:1.8s
            • 方法 2:47 毫秒

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

            【讨论】:

            • 我部分同意你的看法。如果您正在使用 huge 数组(数百个,事件数千个 Mo),或者可能在某些受限系统中,此方法可能不适合,因为您可能会遇到 large-block-from-heap-分配麻烦(但无论您选择哪种方法,您都可能会被搞砸)。但在大多数情况下,这种方法相当安全,而且非常有效。
            【解决方案8】:

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

            int main(void) {
                size_t m = 4, n = 3;
                int (*2D_array)[m];
                2D_array = malloc(n * sizeof *2D_array);
                free(2D_array);
                return 0;
            }
            

            【讨论】:

            • 2d_array 不是一个有效的标识符!
            猜你喜欢
            • 2016-06-21
            • 1970-01-01
            • 1970-01-01
            • 2012-02-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-07-14
            相关资源
            最近更新 更多