Avant toute chose, je trouve que la qualité rédactionnelle de ton code est déjà remarquable. On voit que tu t'y attaches avec sérieux.
À Sve@r et obsidian : je vais m'atteler à l'étude des fonctions
memcpy() et
memmove() après mes examens vu que ça risque de me prendre un certain temps.
C'est une bonne chose de ne pas s'embrouiller la tête avec des choses annexes lorsque l'on est en période d'examen. Cela dit, il n'y a aucun piège dans memcpu() et memmove(). La première copie juste un bloc de n octets (enfin : bytes) d'un endroit A à un endroit B. memmove() fait de même mais en prenant soin d'éviter tout écrasement si les emplacements se chevauchent. Le plus simple pour y arriver consistant à commencer la copie par la fin des données si le bloc destination se trouve après le bloc source.
D'autre part, j'ai fait une petite expérience dans cette pause dans mes révisions. J'ai créé un tableau bidimensionnel grâce aux pointeurs et à la fonction
calloc(), mais je n'en suis pas tout à fait satisfait. Pourquoi ma satisfaction n'est-elle pas complète ? En fait, je pense qu'il y a un moyen de se départir du vecteur
int *arpAbscisse[], mais je ne vois pas comment. Un peu d'aide, s'il vous plaît.
En fait, tu mets le doigt sur un détail subtil mais très fondamental avec les tableaux à plusieurs dimensions : un tableau multi-dimensionnel n'est pas un « tableau de tableaux ». Cela reste une zone de mémoire consécutive et d'un seul tenant, qui contient tous tes éléments.
La question est légitime car on pourrait tout-à-fait s'attendre à ce qu'ajouter des crochets à la suite d'une expression quelconque provoque sa mise en parallèle, fût-ce déjà un tableau.
Il n'y a pas non plus n pointeurs automatiquement déclarés, un pour chaque ligne. Là encore, seule la place pour les éléments est réservée en mémoire, et le nom du tableau seul renvoie l'adresse du début de cette zone, qui est donc forcément celle du premier élément, même à plusieurs dimensions. C'est important parce que dans le cas de malloc() successifs comme tu le fais, tu es assurée que chaque « ligne » est en un seul morceau, certes, rien ne te garantit que les différentes lignes soient consécutives en mémoire. Ça peut être un mal comme un bien, dans la mesure où allouer un très gros bloc d'un seul tenant peut être impossible si la mémoire est trop fragmentée, même si la mémoire totale disponible reste supérieure à la taille de ce bloc.
La façon la plus sûre de déclarer dynamiquement un tableau multi-dimensionnel, donc, reste l'allocation d'une zone de mémoire correspondant à tous ses éléments :
pTab = calloc ((size_t) NB_ORDONNEES * NB_ABSCISSES,sizeof (int));
Mais si tu veux rester propre d'un point de vue sémantique, tu peux quand même allouer de la place pour « NB_ABSCISSES » tableaux de « NB_ORDONNEES » entiers :
pTab = calloc ((size_t) NB_ORDONNEES,sizeof (int[NB_ORDONNEES));
ATTENTION : Chose importante, tu n'as plus de liste de pointeurs indiquant le début de chaque ligne. Ton pointeur pTab ne peut donc plus être déclarée « int ** pTab; ».
À la place, le plus exact d'un point de vue sémantique, toujours, est d'indiquer qu'il pointe un tableau d'entiers et dont les dimensions sont celles que tu as déclarées. Attention, c'est subtil, encore une fois : de la même façon qu'un pointeur « int * » sur un tableau fait « disparaître » la première dimension, il va falloir définir un « pointeur vers une ligne d'entiers » :
int (* pTab) [NB_ORDONNEES] = NULL;
EDIT : Je paraphrase encore Sve@r sur certains points, le temps de finir de rédiger mon commentaire. :-) Je pense qu'il ne m'en voudra pas.
Partager