Namespaces
Variants

memcpy, memcpy_s

From cppreference.net
< c ‎ | string ‎ | byte
Défini dans l'en-tête <string.h>
(1)
void * memcpy ( void * dest, const void * src, size_t count ) ;
(jusqu'à C99)
void * memcpy ( void * restrict dest, const void * restrict src, size_t count ) ;
(depuis C99)
errno_t memcpy_s ( void * restrict dest, rsize_t destsz,
const void * restrict src, rsize_t count ) ;
(2) (depuis C11)
1) Copie count caractères de l'objet pointé par src vers l'objet pointé par dest . Les deux objets sont interprétés comme des tableaux de unsigned char .
Le comportement est indéfini si l'accès se produit au-delà de la fin du tableau dest . Si les objets se chevauchent (ce qui constitue une violation du contrat restrict ) (depuis C99) , le comportement est indéfini. Le comportement est indéfini si dest ou src est un pointeur invalide ou nul.
2) Identique à (1) , sauf que les erreurs suivantes sont détectées à l'exécution et entraînent la mise à zéro de l'intégralité de la plage de destination [ dest, dest + destsz ) (si dest et destsz sont tous deux valides), ainsi que l'appel de la fonction constraint handler actuellement installée :
  • dest ou src est un pointeur nul
  • destsz ou count est supérieur à RSIZE_MAX
  • count est supérieur à destsz (un dépassement de tampon se produirait)
  • les objets source et destination se chevauchent
Le comportement est indéfini si la taille du tableau de caractères pointé par dest < count <= destsz ; en d'autres termes, une valeur erronée de destsz n'expose pas le dépassement de tampon imminent.
Comme pour toutes les fonctions à vérification de limites, memcpy_s n'est garantie d'être disponible que si __STDC_LIB_EXT1__ est défini par l'implémentation et si l'utilisateur définit __STDC_WANT_LIB_EXT1__ à la constante entière 1 avant d'inclure <string.h> .

Table des matières

Paramètres

dest - pointeur vers l'objet de destination de la copie
destsz - nombre maximal d'octets à modifier dans la destination (généralement la taille de l'objet de destination)
src - pointeur vers l'objet source de la copie
count - nombre d'octets à copier

Valeur de retour

1) Retourne une copie de dest
2) Retourne zéro en cas de succès et une valeur non nulle en cas d'erreur. De plus, en cas d'erreur, si dest n'est pas un pointeur nul et que destsz est valide, écrit destsz octets nuls dans le tableau de destination.

Notes

memcpy peut être utilisé pour définir le type effectif d'un objet obtenu par une fonction d'allocation.

memcpy est la routine de bibliothèque la plus rapide pour la copie mémoire-à-mémoire. Elle est généralement plus efficace que strcpy , qui doit analyser les données qu'elle copie, ou memmove , qui doit prendre des précautions pour gérer les chevauchements d'entrées.

Plusieurs compilateurs C transforment les boucles de copie mémoire appropriées en appels memcpy .

Lorsque l'aliasing strict interdit d'examiner la même mémoire comme des valeurs de deux types différents, memcpy peut être utilisé pour convertir les valeurs.

Exemple

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
    // utilisation simple
    char source[] = "once upon a midnight dreary...", dest[4];
    memcpy(dest, source, sizeof dest);
    for(size_t n = 0; n < sizeof dest; ++n)
        putchar(dest[n]);
    // définition du type effectif de la mémoire allouée comme int
    int *p = malloc(3*sizeof(int));   // la mémoire allouée n'a pas de type effectif
    int arr[3] = {1,2,3};
    memcpy(p,arr,3*sizeof(int));      // la mémoire allouée a maintenant un type effectif
    // réinterprétation des données
    double d = 0.1;
//    int64_t n = *(int64_t*)(&d); // violation de l'aliasing strict
    int64_t n;
    memcpy(&n, &d, sizeof d); // OK
    printf("\n%a is %" PRIx64 " as an int64_t\n", d, n);
#ifdef __STDC_LIB_EXT1__
    set_constraint_handler_s(ignore_handler_s);
    char src[] = "aaaaaaaaaa";
    char dst[] = "xyxyxyxyxy";
    int r = memcpy_s(dst,sizeof dst,src,5);
    printf("dst = \"%s\", r = %d\n", dst,r);
    r = memcpy_s(dst,5,src,10);            // count est supérieur à destsz  
    printf("dst = \"");
    for(size_t ndx=0; ndx<sizeof dst; ++ndx) {
        char c = dst[ndx];
        c ? printf("%c", c) : printf("\\0");
    }
    printf("\", r = %d\n", r);
#endif
}

Sortie possible :

once
0x1.999999999999ap-4 is 3fb999999999999a as an int64_t
dst = "aaaaayxyxy", r = 0
dst = "\0\0\0\0\0yxyxy", r = 22

Références

  • Norme C11 (ISO/CEI 9899:2011) :
  • 7.24.2.1 La fonction memcpy (p: 362)
  • K.3.7.1.1 La fonction memcpy_s (p: 614)
  • Norme C99 (ISO/CEI 9899:1999) :
  • 7.21.2.1 La fonction memcpy (p: 325)
  • Norme C89/C90 (ISO/CEI 9899:1990) :
  • 4.11.2.1 La fonction memcpy

Voir aussi

(C23)
copie un tampon vers un autre, en s'arrêtant après le délimiteur spécifié
(fonction)
déplace un tampon vers un autre
(fonction)
copie un certain nombre de caractères larges entre deux tableaux non chevauchants
(fonction)