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 lon 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 nest pas celui recherché. En recopiant dans lordre inverse, 04
est copié sur 07
, puis 03
sur 06
, etc., et lon 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 nest fait si source == dest
. Noter aussi que dans le sens descendant, linitialisation 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 deffet de bord (voir plus loin).