Namespaces
Variants

memmove, memmove_s

From cppreference.net
< c ‎ | string ‎ | byte
Défini dans l'en-tête <string.h>
void * memmove ( void * dest, const void * src, size_t count ) ;
(1)
errno_t memmove_s ( void * dest, rsize_t destsz, const void * src, rsize_t count ) ;
(2) (depuis C11)
1) Copie count caractères depuis l'objet pointé par src vers l'objet pointé par dest . Les deux objets sont interprétés comme des tableaux de unsigned char . Les objets peuvent se chevaucher : la copie s'effectue comme si les caractères étaient copiés vers un tableau temporaire de caractères puis les caractères étaient copiés depuis ce tableau vers dest .
Le comportement est indéfini si l'accès se produit au-delà de la fin du tableau dest. Le comportement est indéfini si dest ou src est un pointeur invalide ou nul.
2) Identique à (1) , sauf qu'en cas de détection des erreurs suivantes à l'exécution, il remet à zéro toute la plage de destination [ dest, dest + destsz ) (si à la fois dest et destsz sont valides) et appelle 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)
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 ne révèle pas le dépassement de tampon imminent.
Comme pour toutes les fonctions à vérification de limites, memmove_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. Également en cas d'erreur, si dest n'est pas un pointeur nul et destsz est valide, écrit destsz octets nuls dans le tableau de destination.

Notes

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

Bien que spécifiée "comme si" un tampon temporaire était utilisé, les implémentations réelles de cette fonction n'entraînent pas la surcharge de la double copie ou de la mémoire supplémentaire. Une approche courante (glibc et bsd libc) consiste à copier les octets vers l'avant depuis le début du tampon si la destination commence avant la source, et vers l'arrière depuis la fin sinon, avec un recours à la fonction plus efficace memcpy lorsqu'il n'y a aucun chevauchement.

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

Exemple

#define __STDC_WANT_LIB_EXT1__ 1
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
    char str[] = "1234567890";
    puts(str);
    memmove(str + 4, str + 3, 3); // copier de [4,5,6] vers [5,6,7]
    puts(str);
    // 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};
    memmove(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;
    memmove(&n, &d, sizeof d); // OK
    printf("%a est %" PRIx64 " comme int64_t\n", d, n);
#ifdef __STDC_LIB_EXT1__
    set_constraint_handler_s(ignore_handler_s);
    char src[] = "aaaaaaaaaa";
    char dst[] = "xyxyxyxyxy";
    int r = memmove_s(dst, sizeof dst, src, 5);
    printf("dst = \"%s\", r = %d\n", dst, r);
    r = memmove_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 :

1234567890
1234456890
0x1.999999999999ap-4 est 3fb999999999999a comme int64_t
dst = "aaaaayxyxy", r = 0
dst = "\0\0\0\0\0yxyxy", r = 22

Références

  • Norme C23 (ISO/CEI 9899:2024) :
  • 7.24.2.2 La fonction memmove (p: TBD)
  • K.3.7.1.2 La fonction memmove_s (p: TBD)
  • Norme C17 (ISO/CEI 9899:2018) :
  • 7.24.2.2 La fonction memmove (p: 264)
  • K.3.7.1.2 La fonction memmove_s (p: 446)
  • Norme C11 (ISO/CEI 9899:2011) :
  • 7.24.2.2 La fonction memmove (p: 363)
  • K.3.7.1.2 La fonction memmove_s (p: 615)
  • Norme C99 (ISO/CEI 9899:1999) :
  • 7.21.2.2 La fonction memmove (p. 326)
  • Norme C89/C90 (ISO/IEC 9899:1990) :
  • 4.11.2.2 La fonction memmove

Voir aussi

copie un tampon vers un autre
(fonction)
copie une certaine quantité de caractères larges entre deux tableaux, potentiellement chevauchants
(fonction)
Documentation C++ pour memmove