Solution de l’exercice 3.7

Lorsque dest est plus grand que source, et que les zones mémoire se recouvrent, il faut recopier du dernier octet au premier. Imaginons que la mémoire pointée par source contienne les octets suivants :

01 02 03 04 05 06 07 08 09

que dest soit égal à source +3 (et donc pointe sur 04), et que l’on souhaite recopier 4 octets. Dans ce cas, en recopiant du premier au dernier, 01 est copié sur 04, 02 sur 05, etc., donnant le résultat :

01 02 03 01 02 03 01 08 09

qui n’est pas celui recherché. En recopiant dans l’ordre inverse, 04 est copié sur 07, puis 03 sur 06, etc., et l’on obtient par contre le bon résultat :

01 02 03 01 02 03 04 08 09

Retenir donc que dans ce genre de copie, si la zone de destination suit la zone source, il faut recopier de la fin au début, et inversement sinon.

On obtient donc la fonction suivante :

void *memmove(void *dest, void *source,  int taille){     char *d = dest, *s = source;     if (d > s) {                  d += taille;                  s += taille;                  while (taille-- > 0) *(--d) = *(--s);                  } else     if (d < s)                  while (taille-- > 0) *(d++) = *(s++);}

On notera que, bien sûr, rien n’est fait si source == dest. Noter aussi que dans le sens descendant, l’initialisation de d et s les place une case trop loin (successeur du dernier octet à copier), ce qui exige une pré-incrémentation dans la boucle. Enfin la modification de taille est autorisée et ne provoque pas d’effet de bord (voir plus loin).


Retour au texte.