Différence entre memcpy et memmove
Résolu/Fermé
leoliom
Messages postés
171
Date d'inscription
jeudi 21 juillet 2016
Statut
Membre
Dernière intervention
20 février 2024
-
24 févr. 2022 à 11:15
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 - 7 mars 2022 à 17:31
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 - 7 mars 2022 à 17:31
A voir également:
- Memmove vs memcpy
- Udp vs tcp - Guide
- Dual core vs i5 ✓ - Forum Processeur
- Max vs netflix - Accueil - Streaming
- Psp 2000 vs 3000 ✓ - Forum PSP
- Mo vs mb ✓ - Forum Matériel & Système
9 réponses
jeannets
Messages postés
27576
Date d'inscription
dimanche 9 septembre 2007
Statut
Contributeur
Dernière intervention
24 décembre 2024
Ambassadeur
5 878
24 févr. 2022 à 11:50
24 févr. 2022 à 11:50
Bonjour,
Memcpy est une copie de mémoire sur une autre adresse, sans détruire l'original
https://man7.org/linux/man-pages/man3/memcpy.3.html
Tandis que Memmove est un déplacement d'une mémoire, Contrairement à Memcpy, il efface la source..
https://www.man7.org/linux/man-pages/man3/memmove.3.html
Les attribues définissent la source, la destination et la taille des valeurs déplacées ou copiées...
Bien sur pour que tout soit synchro, il faut connaitre sa leçon et les valeurs en mouvements. faire des exemples sur du papier quadrillé..
Memcpy est une copie de mémoire sur une autre adresse, sans détruire l'original
https://man7.org/linux/man-pages/man3/memcpy.3.html
Tandis que Memmove est un déplacement d'une mémoire, Contrairement à Memcpy, il efface la source..
https://www.man7.org/linux/man-pages/man3/memmove.3.html
Les attribues définissent la source, la destination et la taille des valeurs déplacées ou copiées...
Bien sur pour que tout soit synchro, il faut connaitre sa leçon et les valeurs en mouvements. faire des exemples sur du papier quadrillé..
leoliom
Messages postés
171
Date d'inscription
jeudi 21 juillet 2016
Statut
Membre
Dernière intervention
20 février 2024
2
24 févr. 2022 à 12:18
24 févr. 2022 à 12:18
J’ai lu aussi ce site mais j’ai pas compris.Comme vous le dites le seul moyen de comprendre c’est par un schéma sauf que moi je sais pas j’ai du mal
Peut été un petit exemple me permettra de mieux comprendre
Peut été un petit exemple me permettra de mieux comprendre
Dalfab
Messages postés
706
Date d'inscription
dimanche 7 février 2016
Statut
Membre
Dernière intervention
2 novembre 2023
101
24 févr. 2022 à 14:41
24 févr. 2022 à 14:41
Les 2 fonctions ne se distinguent que dans le cas où il y a recouvrement. C'est quand des cases sont à la fois dans la source à copier et dans la destination.
Exemple tu veux copier les 4 premières cases du tableau suivant dans les 4 dernières:
Si tu utilises
Si tu utilises
Donc s'il n'y a pas recouvrement, les fonctions sont équivalentes (mais
Exemple tu veux copier les 4 premières cases du tableau suivant dans les 4 dernières:
+---+---+---+---+---+---+---+
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+
Si tu utilises
memmove()tu obtiendras le résultat suivant (les 4 dernières reçoivent bien ce qu'il y avait dans les 4 premières)
+---+---+---+---+---+---+---+
| 1 | 2 | 3 | 1 | 2 | 3 | 4 |
+---+---+---+---+---+---+---+
Si tu utilises
memcpy(), cette fonction est un peu "bête", elle va vite mais ne "réfléchit" pas beaucoup! Elle risque de te donner le résultat suivant:
+---+---+---+---+---+---+---+C'est une supposition, essaie de comprendre ce qui l'a perdu et essaie d'écrire un code qui fait cela, ou essaie d'écrire toi même une fonction
| 1 | 2 | 3 | 1 | 2 | 3 | 1 |
+---+---+---+---+---+---+---+
memcpy()et vois pourquoi la fin n'est pas correcte.
Donc s'il n'y a pas recouvrement, les fonctions sont équivalentes (mais
memcpy()est plus rapide), s'il y recouvrement la fonction
memcpy()peut avoir un résultat faux.
leoliom
Messages postés
171
Date d'inscription
jeudi 21 juillet 2016
Statut
Membre
Dernière intervention
20 février 2024
2
Modifié le 2 mars 2022 à 15:00
Modifié le 2 mars 2022 à 15:00
D'après votre exemple:
Est-ce correct?
J'ai pas compris la phrase C'est quand des cases sont à la fois dans la source à copier et dans la destination.
Par exemple dans votre exemple il y a recouvrement pour quel nombre?
int tab[10] = {1, 2, 3, 4, 5, 6, 7}; int tab2[10]; strncpy(tab2,tab1,4); memmove(tab + 3, tab2, strlen(tab)) memcpy(tab + 3, tab2, strlen(tab))
Est-ce correct?
J'ai pas compris la phrase C'est quand des cases sont à la fois dans la source à copier et dans la destination.
Par exemple dans votre exemple il y a recouvrement pour quel nombre?
Dalfab
Messages postés
706
Date d'inscription
dimanche 7 février 2016
Statut
Membre
Dernière intervention
2 novembre 2023
101
Modifié le 2 mars 2022 à 15:02
Modifié le 2 mars 2022 à 15:02
Tu n'as en effet pas compris. Il n'y a qu'un seul tableau et on fait des copies à l'intérieur du tableau. S'il y a deux tableaux alors
Et
Mon exemple c'est :
memcpy()et
memmove()sont indistinguables.
Et
strncpy()et
strlen()sont des fonctions qui s'appliquent à des chaines de caractères. Ici ce sont des tableaux d'entiers, ça n'a rien à voir et ces fonctions font alors n'importe quoi dans ton code!
Mon exemple c'est :
int tab[7] = {1, 2, 3, 4, 5, 6, 7}; memmove( &tab[3], &tab[0], 4*sizeof(int) ); // copier tab[0]tab[1]tab[2]tab[3] dans tab[3]tab[4]tab[5]tab[6]. for ( int i = 0 ; i < 7 ; ++i ) printf( "%d ", tab[i] );
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
leoliom
Messages postés
171
Date d'inscription
jeudi 21 juillet 2016
Statut
Membre
Dernière intervention
20 février 2024
2
Modifié le 25 févr. 2022 à 17:03
Modifié le 25 févr. 2022 à 17:03
J pense que c'est bon j'ai compris la subtilité entre les deux,ça m'a pris beaucoup de temps avant de comprendre
Merci
Merci
leoliom
Messages postés
171
Date d'inscription
jeudi 21 juillet 2016
Statut
Membre
Dernière intervention
20 février 2024
2
Modifié le 2 mars 2022 à 15:11
Modifié le 2 mars 2022 à 15:11
Bonjour,
Pour comprendre le fonctionnement de
Exemple :
Si je prends une autre implémentation sur Internet :
Je comprends plus, leur implémentation en C me paraissait correcte. Qu'est-ce qui ne va pas ? Qu'est-ce qui manque à ces fonctions pour qu'il fasse le même travail que
Pour comprendre le fonctionnement de
memcpyet
memmove. J'ai regardé leur implémentation en C, mais bizarrement elle ne fait pas toujours la même chose. Pour
memmove, ça marche, mais pas
memcpy.
Exemple :
#include <stdio.h> #include <string.h> void * Memcpy(void* dst, const void* src, unsigned int cnt) { char *pszDest = (char *)dst; const char *pszSource =( const char*)src; if((pszDest!= NULL) && (pszSource!= NULL)) { while(cnt) //till cnt { //Copy byte by byte *(pszDest++)= *(pszSource++); --cnt; } } return dst; } int main(void){ char chaine[7] = "aabbcc"; Memcpy(chaine + 2, chaine, 4); printf("%s\n", chaine); return 0; }
-
Memcpy
renvoieaaaaaa
; -
memcpy
renvoieaaaabb
.
Si je prends une autre implémentation sur Internet :
#include <string.h> #include <stdio.h> void myMemCpy(void *dest, void *src, size_t n){ // Typecast src and dest addresses to (char *) char *csrc = (char *)src; char *cdest = (char *)dest; // Copy contents of src[] to dest[] for (int i = 0; i < n; i++) cdest[i] = csrc[i]; } int main(void){ char str1[7] = "aabbcc"; myMemMove(str1 + 2, str1, 4); printf("New string: %s\n", str1); return 0; }
-
mymencpy
renvoieaaaaaa
; -
memcpy
renvoieaaaabb
.
Je comprends plus, leur implémentation en C me paraissait correcte. Qu'est-ce qui ne va pas ? Qu'est-ce qui manque à ces fonctions pour qu'il fasse le même travail que
memcpy?
mamiemando
Messages postés
33446
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
20 décembre 2024
7 812
2 mars 2022 à 15:40
2 mars 2022 à 15:40
Bonjour,
Que fond
De manière générale il suffit de regarder ce que racontent
Que se passe-t'il si les blocs se chevauchent ?
Maintenant, regardons un peu plus dans le détail ce qui se passe, si le bloc source et cible se chevauchent. Ici, il faut être prudent, car tu peux craindre des effets de bords (typiquement si tu écris dans la zone que tu t'apprêtes à lire):
Pourquoi existe-il une fonction
Il y a plusieurs raisons, et avant de commencer il est important de comprendre comment est stockée une chaîne de caractère en mémoire. Le problème de fond, c'est qu'une chaîne de caractère peut être arbitrairement longue (contrairement à un
Le choix qui a été fait, c'est de marquer la chaîne par un caractère terminal
Si on revient à
Comme
Retour à ton code
Dans ton cas, vu que tu manipules des chaînes, il ne suffit pas de recopier les lettres pour que ça se passe bien, il faut s'assurer que la chaîne que tu vas copier ou que tu vas afficher possède bien son caractère terminal
Bonne chance
Que fond
memmoveet
memcpy?
De manière générale il suffit de regarder ce que racontent
man memmoveet
man memcpy(à taper dans google ou dans un terminal si tu es sous Linux)
-
memcpy
copie un bloc mémoire d'une adresse vers une autre adresse. Le bloc cible doit être préalloué en mémoire pour accueillir le bloc source, sinon tu as en général une erreur de segmentation. La recopie se fait typiquement octet par octet (et pour rappel un caractère ASCII (char
) fait un octet, c'est pourquoi cette fonction est très proche destrcpy
et donc dans<string.h>
) : on lit l'octet source courant, on le recopie dans l'octet cible correspondant, et on répète l'opération jusqu'à avoir traité tout le bloc. - Officiellement
memmove
déplace un bloc mémoire d'une adresse vers une autre adresse. Le bloc cible doit être préalloué en mémoire pour accueillir le bloc source, sinon tu as en général une erreur de segmentation. Il n'y aucune garantie sur ce qui restera au niveau du bloc de départ mais la plupart des implémentations se contentent de le laisser tel quel afin d'améliorer la performance (et pour ces implémentation,memmove
fait exactement la même chose quememcpy
quand les blocs sources et cibles ne se chevauchent pas). Dans ces situations, on utilise plusmemmove
pour la lisibilité du programme. Cependant le bloc source ne doit plus être lu car selon l'implémentation, il pourrait avoir été réinitialisé.
Que se passe-t'il si les blocs se chevauchent ?
Maintenant, regardons un peu plus dans le détail ce qui se passe, si le bloc source et cible se chevauchent. Ici, il faut être prudent, car tu peux craindre des effets de bords (typiquement si tu écris dans la zone que tu t'apprêtes à lire):
- D'après cette page,
memmove
passe par un buffer intermédiaire pour se prémunir de ces effets de bord . - D'après cette page, ce n'est pas le cas de
memcpy
, et donc il faut être vigilant à ce qu'on fait.
Pourquoi existe-il une fonction
strcpyet
memcpy?
Il y a plusieurs raisons, et avant de commencer il est important de comprendre comment est stockée une chaîne de caractère en mémoire. Le problème de fond, c'est qu'une chaîne de caractère peut être arbitrairement longue (contrairement à un
uint32_tqui fait par définition exactement 32 bits soit 4 octets). Comment garder trace de la taille ?
Le choix qui a été fait, c'est de marquer la chaîne par un caractère terminal
'\0'(qui correspond à l'
uint8_t
0. Toutes les fonctions
str*(
strcpy,
strlen, ...) et
printfs'appuient sur ce caractère terminal pour savoir quand s'arrêter. Cela signifie que la chaîne
"abc"fait 4 octets
{'a', 'b', 'c', '\0'}et non 3 comme on pourrait le croire. Cela signifie qu'il ne faut pas oublier ce fameux caractère terminal dès qu'on manipule des chaînes. Sans lui, les fonctions
str*jusqu'à rencontrer (par chance) un octet qui vaut 0 et qui souvent est en dehors d'une zone mémoire allouée, engendrant une erreur de segmentation.
Si on revient à
memcpy, on s'aperçoit qu'on peut reproduire
strcpysous réserve de connaître la longueur de la chaîne à recopier (sans oublier son
'\0'terminal).
Comme
memcpyest conçue pour manipuler un bloc mémoire arbitraire -d'où, dans son prototype, le type
const void *pour le bloc source (read only) et le type
void *pour le bloc cible (read write)- (en particulier, quelque chose qui n'est pas une chaîne et donc quelque chose qui n'est pas nécessairement terminé par
'\0'), il faut lui indiquer combien d'octets recopier. C'est le rôle de son troisième paramètre.
Retour à ton code
Dans ton cas, vu que tu manipules des chaînes, il ne suffit pas de recopier les lettres pour que ça se passe bien, il faut s'assurer que la chaîne que tu vas copier ou que tu vas afficher possède bien son caractère terminal
'\0'. C'est quelque chose que garantit par
strcpy, mais pas par
memcpy.
Bonne chance
leoliom
Messages postés
171
Date d'inscription
jeudi 21 juillet 2016
Statut
Membre
Dernière intervention
20 février 2024
2
6 mars 2022 à 10:58
6 mars 2022 à 10:58
Ah donc les implémenterions de ces fonctions ne sont pas bonne car on prend pas en compte le caractère terminal de fin de chaine
Esceque je dois modifier le code de sorte qu’il ajoute à la fin de la copie ce caractère pour que ça marche ?
Esceque je dois modifier le code de sorte qu’il ajoute à la fin de la copie ce caractère pour que ça marche ?
Dalfab
Messages postés
706
Date d'inscription
dimanche 7 février 2016
Statut
Membre
Dernière intervention
2 novembre 2023
101
7 mars 2022 à 07:34
7 mars 2022 à 07:34
>>> Ah donc les implémenterions de ces fonctions ne sont pas bonne car on prend pas en compte le caractère terminal de fin de chaine
Non. As-tu vus quelque part que memcpy() devait mettre un terminateur de chaine?
>>> Esceque je dois modifier le code de sorte qu’il ajoute à la fin de la copie ce caractère pour que ça marche ?
Non.
La fonction memcpy(), la fonction mymencpy() et la fonction Memcpy() sont toutes les 3 conformes.
La norme dit :
- s'il n'y a pas recouvrement, la fonction doit copier (tu peux vérifier que les 3 fonctions effectuent bien la copie).
- s'il y a recouvrement, le résultat est totalement imprévisible (donc le résultat est tout à fait quelconque, ça n'a aucun sens de comparer les résultats dans ce cas!)
C'est tout à fait possible que la fonction memcpy() soit différente d'elle même si tu changes le contexte!
Non. As-tu vus quelque part que memcpy() devait mettre un terminateur de chaine?
>>> Esceque je dois modifier le code de sorte qu’il ajoute à la fin de la copie ce caractère pour que ça marche ?
Non.
La fonction memcpy(), la fonction mymencpy() et la fonction Memcpy() sont toutes les 3 conformes.
La norme dit :
- s'il n'y a pas recouvrement, la fonction doit copier (tu peux vérifier que les 3 fonctions effectuent bien la copie).
- s'il y a recouvrement, le résultat est totalement imprévisible (donc le résultat est tout à fait quelconque, ça n'a aucun sens de comparer les résultats dans ce cas!)
C'est tout à fait possible que la fonction memcpy() soit différente d'elle même si tu changes le contexte!
char str1[7] = "aabbcc"; char str2[7] = "aabbcc"; memcpy(str1 + 2, str1, 4); printf("New string: %s\n", str1); memcpy(str2 + 2, str2, 4); printf("New string: %s\n", str2);Ce code peut tout à fait retourner 2 résultats différents avec apparemment les mêmes données en entrée, ou avoir un résultat différent en version debug et en version release, essaie. C'est sans issue de vouloir reproduire ce que tu vois dans le cas où la fonction a un résultat indéfini!
mamiemando
Messages postés
33446
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
20 décembre 2024
7 812
>
Dalfab
Messages postés
706
Date d'inscription
dimanche 7 février 2016
Statut
Membre
Dernière intervention
2 novembre 2023
7 mars 2022 à 16:33
7 mars 2022 à 16:33
Pour compléter ce que dit Dalfab :
- les fonctions
str*
font l'hypothèse que le bloc mémoire à copier est de taille arbitraire mais peut-être vu comme une chaîne de caractère terminée par'\0'
; - les fonctions
mem*
ne font pas d'hypothèse sur un caractère d'arrêt (ce qui permet de recopier n'importe quel séquence d'octet, mais à besoin d'une taille pour savoir quand s'arrêter ; - dans tous les cas, ces fonctions ne doivent lire et écrire que dans des zones mémoires allouées par le programme, sans quoi une erreur de segmentation sera déclenchée.
leoliom
Messages postés
171
Date d'inscription
jeudi 21 juillet 2016
Statut
Membre
Dernière intervention
20 février 2024
2
7 mars 2022 à 17:31
7 mars 2022 à 17:31
Merci pour toutes ces réponses ,j’i mieux compris maintenant