Выделить память 2d массива в функции C

Как выделить динамическую память для 2d массива в функции? Я пробовал так:

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

Но это не сработает.

Ответ 1

В *arr[i]=(int*)malloc(m*sizeof(int)); ваш код неверен, потому что precedence оператора [] выше, чем * operator: В выражении *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 вызывается только два раза, и поэтому в коде освобождения освобождается вызов только два раза вместо вызова его в цикле. Поэтому этот метод должен быть лучше.

Ответ 2

Если вам не нужно изменять размер массива (ну, вы можете, но il будет немного сложнее), есть более простой/эффективный способ построения 2D-массивов в C.

Посмотрите http://c-faq.com/aryptr/dynmuldimary.html.

Второй метод (для массива с именем array2) довольно прост, менее болезнен (попробуйте добавить тесты для возвращаемого значения mallocs) и более эффективным.

Я только что сравнил это, для массива 200x100, выделенного и освобожденного 100000 раз:

  • Способ 1:1,8 с
  • Способ 2: 47 мс

И данные в массиве будут более смежными, что может ускорить работу (вы можете получить более эффективные методы для копирования, reset... массив, выделенный таким образом).

Ответ 3

Рассмотрим это: Простое выделение

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

Ответ 4

Скорее распределяя память во многих разных блоках, можно выделить это в последовательном блоке памяти. Выполните следующие действия:

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

Ответ 5

Это излишне сложный способ выделения пространства для массива. Рассмотрим это:

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

Ответ 6

Я попробовал следующий код для выделения памяти в 2-мерный массив.

    #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

Чтобы понять 2-мерный массив в терминах указателей, нам нужно понять, как он будет выделен в памяти, это должно быть примерно так: -

                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 = к. Точно так же он будет указывать на 2 и 3 в следующих итерациях в цикле.

Перед следующей итерацией внешнего цикла двойной указатель увеличивается в следующей итерации, как показано в этом примере, указатель теперь находится в 0x1004 и указывает на целочисленный указатель, который представляет собой массив целых чисел 4,5, 6 и аналогично для следующих итераций в цикле.

Ответ 7

2d Массив массива с помощью 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;

Ответ 8

Попробуйте использовать следующий код:

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