68 votes

Utilisation de malloc pour l'allocation de tableaux multidimensionnels avec différentes longueurs de ligne

J'ai le code C suivant:

    int *a;
   size_t size = 2000*sizeof(int);
   a = (int *) malloc(size);
 

qui fonctionne bien. Mais si j'ai les éléments suivants:

    char **b = malloc(2000*sizeof *b);
 

où chaque élément de b a une longueur différente.

Comment est-il possible de faire la même chose pour b comme je l’ai fait pour a ; c'est-à-dire que le code suivant serait correct?

    char *c;
   size_t size = 2000*sizeof(char *);
   c = (char *) malloc(size);
 

80voto

Nikolai N Fetissov Points 52093

Tout d’abord, vous devez allouer un tableau de pointeurs comme c = ( char** )malloc( N*sizeof( char* )) , puis allouer à chaque ligne un appel distinct à malloc , probablement dans la boucle:

 
/* N is the number of rows */
if (( c = ( char** )malloc( N*sizeof( char* ))) == NULL )
{ /* error */ }

for ( i = 0; i < N; i++ )
{
  /* x_i here is the size of given row, no need to
   * multiply by sizeof( char ), it's always 1
   */
  if (( c[i] = ( char* )malloc( x_i )) == NULL )
  { /* error */ }

  /* probably init the row here */
}

/* access matrix elements: c[i] give you a pointer
 * to the row array, c[i][j] indexes an element
 */
c[i][j] = 'a';
 

Si vous connaissez le nombre total d'éléments (par exemple, N*M ), vous pouvez le faire en une seule allocation.

49voto

John Bode Points 33046

La forme typique pour l’allocation dynamique d’un tableau NxM de type T est

 T **a = malloc(sizeof *a * N);
if (a)
{
  for (i = 0; i < N; i++)
  {
    a[i] = malloc(sizeof *a[i] * M);
  }
}
 

Si chaque élément du tableau a une longueur différente, remplacez M par la longueur appropriée pour cet élément; par exemple

 T **a = malloc(sizeof *a * N);
if (a)
{
  for (i = 0; i < N; i++)
  {
    a[i] = malloc(sizeof *a[i] * length_for_this_element);
  }
}
 

29voto

Ramesh Points 154

L'allocation de mémoire équivalente pour char a[10][20] serait la suivante.

 char **a;

a=(char **) malloc(10*sizeof(char *));

for(i=0;i<10;i++)
    a[i]=(char *) malloc(20*sizeof(char));
 

J'espère que cela semble simple à comprendre.

10voto

Dmitry Aleks Points 116

L'autre approche consisterait à allouer un bloc de mémoire contigu comprenant un bloc d'en-tête pour les pointeurs vers des lignes ainsi qu'un bloc de corps pour stocker les données réelles dans des lignes. Ensuite, marquez simplement la mémoire en affectant des adresses de mémoire dans le corps aux pointeurs de l’en-tête, ligne par ligne. Cela ressemblerait à ceci:

 int** 2dAlloc(int rows, int* columns) {    
    int header = rows * sizeof(int*);

    int body = 0;
    for(int i=0; i<rows; body+=columnSizes[i++]) {  
    }
    body*=sizeof(int);

    int** rowptr = (int**)malloc(header + body);

    int* buf  = (int*)(rowptr + rows);
    rowptr[0] = buf;
    int k;
    for(k = 1; k < rows; ++k) {
        rowptr[k] = rowptr[k-1] + columns[k-1];
    }
    return rowptr;
}

int main() {
    // specifying column amount on per-row basis
    int columns[] = {1,2,3};
    int rows = sizeof(columns)/sizeof(int);
    int** matrix = 2dAlloc(rows, &columns);

    // using allocated array
    for(int i = 0; i<rows; ++i) {
        for(int j = 0; j<columns[i]; ++j) {
            cout<<matrix[i][j]<<", ";
        }   
            cout<<endl;
    }

    // now it is time to get rid of allocated 
    // memory in only one call to "free"
    free matrix;
}
 

L'avantage de cette approche est la libération élégante de mémoire et la possibilité d'utiliser une notation de type tableau pour accéder aux éléments du tableau 2D résultant.

3voto

plinth Points 26817

Si chaque élément de b a des longueurs différentes, vous devez faire quelque chose comme:

 int totalLength = 0;
for_every_element_in_b {
    totalLength += length_of_this_b_in_bytes;
}
return (char **)malloc(totalLength);
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X