5 votes

différence entre l'allocation de mémoire à un tableau 2D en une seule fois ou ligne par ligne

Quel serait l'impact sur l'accès au tableau ou sur l'allocation de la mémoire pour ces deux cas ?

1.

    int **arr;
    arr = malloc( sizeof(int) * row * column );

2.

    int **arr;
    arr = malloc( sizeof(*arr) * row);
    for(i=0; i<row; i++)
        arr[i] = malloc( sizeof( **arr) * column));

6voto

AndreyT Points 139512
  • Tout d'abord, l'"impact" est que votre première méthode est cassée. Elle ne fonctionnera pas à travers un int ** pointeur.

    Afin d'allouer un tableau 2D en une seule fois comme vous essayez de le faire dans votre première méthode, vous devez en fait allouer un tableau 1D de taille suffisante.

    int *arr = malloc( row * column * sizeof *arr );
    // Note: `int *`, not `int **`

    et effectuer l'accès en recalculant manuellement l'index, par exemple au lieu de faire arr[i][j] vous devez faire arr[i * column + j] .

    Essayer de stocker le pointeur alloué dans int **arr et ensuite accéder à votre tableau comme arr[i][j] conduira simplement à des crashs.

  • Deuxièmement, votre deuxième méthode est correcte. C'est juste que dans la seconde méthode, vous n'êtes pas vraiment obligé d'allouer la mémoire de second niveau par de multiples opérations indépendantes. malloc appels. Vous pouvez allouer toute la mémoire de second niveau en une seule fois.

    int **arr = malloc( row  * sizeof *arr );
    int *arr_data = malloc( row * column * sizeof *arr_data );

    et ensuite distribuer cette mémoire de second niveau pré-allouée entre les rangées.

    for (i = 0; i < row; i++)
      arr[i] = arr_data + i * column;

    (Bien sûr, vous pouvez attribuer les rangées indépendamment, si vous le souhaitez. Cela fonctionnera également. La raison pour laquelle j'ai voulu les allouer d'un seul coup est de mieux illustrer la similitude entre la première et la deuxième approche, comme commenté ci-dessous).

En examinant ces deux méthodes, vous pouvez facilement constater qu'elles font essentiellement la même chose. La seule différence est que dans la première méthode, vous trouvez le début de la ligne à la volée en calculant arr + i * column à chaque fois (notez que arr[i * column + j] est équivalent à (arr + i * column)[j] ). Dans la deuxième méthode, vous calculez à l'avance tous les débuts de ligne en utilisant la même méthode de calcul que celle utilisée pour le calcul des débuts de ligne. arr_data + i * column et les stocker pour une utilisation ultérieure dans un tableau séparé "d'index de ligne". arr .

Il s'agit donc essentiellement d'un compromis entre l'utilisation de la mémoire (la première méthode nécessite moins de mémoire) et la vitesse (la deuxième méthode est potentiellement, mais pas nécessairement, plus rapide). Dans le même temps, la deuxième méthode prend en charge la syntaxe "naturelle" pour l'accès aux tableaux 2D, à savoir arr[i][j] alors que la première méthode nécessite l'utilisation d'une syntaxe d'accès 1D plus complexe avec un nouveau calcul de l'indice.

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