ti-enxame.com

Alocar memória 2d array na função C

Como alocar memória dinâmica para array 2D na função? Eu tentei assim:

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

Mas isso não funciona.

14
serhii

Seu código está errado em *arr[i]=(int*)malloc(m*sizeof(int)); porque o precedence do operador [] É maior que o operador de deferência *: Na expressão *arr[i], Primeiro arr[i] É avaliado e depois * É aplicado. O que você precisa é o inverso (desreferência arr, depois aplique []).

Use parênteses como este: (*arr)[i] Para substituir a precedência do operador. Agora, seu código deve ficar assim:

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

Para entender melhor o que acontece no código acima, leia esta resposta .

É importante que você sempre desaloque explicitamente a memória alocada dinamicamente quando terminar de trabalhar com ela. Para liberar a memória alocada pela função acima, faça o seguinte:

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

Além disso, a melhor maneira de criar uma matriz 2D é alocar memória contígua com uma única chamada de função malloc() como abaixo:

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
} 

Para desalocar essa memória:

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

Observe que, na segunda técnica, malloc é chamado apenas duas vezes e, no código de desalocação, free é chamado apenas duas vezes, em vez de chamá-lo em um loop. Portanto, essa técnica deve ser melhor.

25
Grijesh Chauhan

Se sua matriz não precisar ser redimensionada (bem, você pode, mas será um pouco mais complicado), existe uma maneira mais fácil/eficiente de criar matrizes 2D em C.

Dê uma olhada em http://c-faq.com/aryptr/dynmuldimary.html .

O segundo método (para o array chamado array2) é bastante simples, menos doloroso (tente adicionar os testes para o valor de retorno dos mallocs) e muito mais eficiente.

Acabei de compará-lo, para um array de 200 x 100, alocado e desalocado 100000 vezes:

  • Método 1: 1.8s
  • Método 2: 47ms

E os dados na matriz serão mais contíguos, o que pode acelerar as coisas (você pode obter técnicas mais eficientes para copiar, redefinir ... uma matriz alocada dessa maneira).

3
Cyrille Faucheux

Em vez de alocar a memória em muitos blocos diferentes, pode-se alocá-la em um bloco consecutivo de memória. Faça o seguinte:

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;
}
2
Smit Patel

Considere o seguinte: Apenas alocação única

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

Liberar, libertar:

free(a);
2
TheMan

Essa é uma maneira desnecessariamente complicada de alocar espaço para uma matriz. Considere isto:

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

Eu tentei o código a seguir para alocar memória para uma matriz bidimensional.

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

A saída do código acima é: -

1 2 3

4 5 6

7 8 9

Para entender a matriz bidimensional em termos de ponteiros, precisamos entender como ela será alocada na memória; deve ser algo como isto: -

                1    2    3
    1000 -->   100  104  108

                4    5    6
    1004 -->   200  204  208

                7    8    9
    1008 -->   300  304  308 

do exposto, entendemos que, quando alocamos memória para o ponteiro p, que é um ponteiro duplo, ele está apontando para uma matriz de números inteiros; portanto, neste exemplo, vemos que o 0x1000 é o ponteiro p.

Esse ponteiro está apontando para o ponteiro inteiro * p, que é uma matriz de números inteiros, quando a memória é alocada dentro do loop for interno, durante a primeira iteração, o ponteiro é 0x100, que está apontando para o valor inteiro 1, quando atribuímos ** p = j. Da mesma forma, ele estará apontando para 2 e 3 nas próximas iterações do loop.

Antes da próxima iteração do loop externo, o ponteiro duplo é incrementado, dentro da próxima iteração, como é visto neste exemplo, o ponteiro está agora em 0x1004 e está apontando para o ponteiro inteiro, que é uma matriz de números inteiros 4,5,6 e similarmente para as próximas iterações no loop.

0
Nanobrains