Quelle est la différence entre memmove
y memcpy
? Lequel utilisez-vous habituellement et comment ?
Réponses
Trop de publicités?Simplement à partir de la norme ISO/IEC:9899, il est bien décrit.
7.21.2.1. La fonction memcpy
[...]
2 La fonction memcpy copie n caractères de l'objet pointé par s2 dans l'objet pointé par s1. l'objet pointé par s1. Si la copie a lieu entre des objets qui se chevauchent, le comportement est indéfini.
Et
7.21.2.2 La fonction memmove
[...]
2 La fonction memmove copie n caractères de l'objet pointé par s2 dans l'objet l'objet pointé par s1. La copie a lieu comme si les n caractères de l'objet pointés par s2 sont d'abord copiés dans un tableau temporaire de n caractères qui ne se chevauche pas les objets pointés par s1 et s2, puis les n caractères de l'objet tableau temporaire sont copiés dans l'objet pointé par s1.
Lequel j'utilise habituellement selon la question, dépend de la fonctionnalité dont j'ai besoin.
En texte clair memcpy()
ne permet pas s1
y s2
de se chevaucher, tandis que memmove()
fait.
Il y a deux façons évidentes de mettre en œuvre mempcpy(void *dest, const void *src, size_t n)
(en ignorant la valeur de retour) :
-
for (char p=src, q=dest; n-->0; ++p, ++q) q=p;
-
char p=src, q=dest; while (n-->0) q[n]=p[n];
Dans le premier cas, la copie se fait de l'adresse basse à l'adresse haute, et dans le second, de l'adresse haute à l'adresse basse. Si la plage à copier se chevauche (comme c'est le cas lors du défilement d'un framebuffer, par exemple), seule une direction d'opération est correcte, et l'autre écrasera les emplacements qui seront lus par la suite.
A memmove()
Dans sa forme la plus simple, l'implémentation testera dest<src
(d'une manière dépendant de la plate-forme), et exécuter la direction appropriée de memcpy()
.
Le code utilisateur ne peut pas faire cela, bien sûr, car même après avoir coulé src
y dst
à un type de pointeur concret, ils ne pointent pas (en général) vers le même objet et ne peuvent donc pas être comparés. Mais la bibliothèque standard peut avoir une connaissance suffisante de la plate-forme pour effectuer une telle comparaison sans provoquer de comportement indéfini.
Notez que dans la réalité, les implémentations ont tendance à être beaucoup plus complexes, afin de tirer le maximum de performance de transferts plus importants (lorsque l'alignement le permet) et/ou d'une bonne utilisation du cache de données. Le code ci-dessus a pour but d'illustrer ce point aussi simplement que possible.
Memmove peut gérer le chevauchement des régions source et destination, alors que memcpy ne le peut pas. Parmi les deux, memcpy est beaucoup plus efficace. Donc, mieux vaut UTILISER memcpy si vous le pouvez.
Référence : https://www.youtube.com/watch?v=Yr1YnOVG-4g Dr. Jerry Cain, (Stanford Intro Systems Lecture - 7) Durée : 36:00
La différence technique a été assez bien documentée par les réponses précédentes. Il convient également de noter les différences pratiques :
Memcpy aura besoin d'environ deux fois la quantité de mémoire pour effectuer la même tâche, mais memmove pourrait prendre beaucoup plus de temps que memcpy.
Exemple :
Disons que vous avez une liste de 100 éléments en mémoire, qui occupe 100 Mo de mémoire. Vous voulez supprimer le premier élément pour n'en garder que 99.
Memcpy nécessitera les 100 Mo d'origine et 99 Mo supplémentaires pour votre projet de recherche. nouveau liste de 99 articles. Environ 199 Mo au total pour effectuer l'opération, mais cela devrait être très rapide.
Memmove, dans le pire des cas, nécessite les 100 Mo d'origine et déplace chaque élément d'une adresse mémoire vers le haut à la fois. Cela ne nécessite que les 100 Mo d'origine, mais sera nettement plus lent que Memcpy.
Bien sûr, la création d'un nouveau pointeur vers le deuxième élément de votre liste aura le même effet que de "laisser tomber" le premier élément de votre liste, mais l'exemple montre bien les différences entre memcpy et memmove.
-- ÉDITER POUR AIDER À CLARIFIER MA RÉPONSE MERDIQUE --
Oui, les implémentations de memcpy() et memmove() ne diffèrent probablement pas dans l'utilisation de la mémoire (je ne sais vraiment pas), mais la façon dont vous les utilisez affectera grandement l'utilisation de la mémoire de votre programme. C'est ce que je voulais dire par les différences pratiques de memcpy() et memmove().
int SIZE = 100;
Item *ptr_item = (Item *) malloc(size_of(Item) * SIZE);
Item *ptr_src_item = ptr_item + 1;
Item *ptr_dst_item = ptr_item;
memmove(ptr_dst_item, ptr_src_item, SIZE - 1);
Cela crée votre liste d'éléments avec le premier élément manquant. Cela ne nécessite pas plus de mémoire pour votre programme que ce qu'il faut pour allouer le bloc de mémoire ptr_item original. Vous ne pouvez pas faire cela en utilisant memcpy()... si vous le faisiez, votre programme devrait allouer environ deux fois plus de mémoire.
int SIZE = 100;
Item *ptr_src_item = (Item *) malloc(size_of(Item) * SIZE);
Item *ptr_dst_item = (Item *) malloc(size_of(Item) * (SIZE - 1));
memcpy(ptr_dst_item, ptr_src_item, SIZE - 1);
Dans ce deuxième bloc de code, le programme nécessiterait deux fois plus de mémoire que dans le premier bloc. Cependant, ce deuxième bloc devrait être beaucoup plus rapide que le premier, surtout si la taille augmente.
C'est ainsi que j'essayais d'expliquer les différences pratiques entre les deux... mais peut-être ai-je tort sur ce point également ?
- Réponses précédentes
- Plus de réponses