Namespaces
Variants

memmove, memmove_s

From cppreference.net
< c ‎ | string ‎ | byte
Definido en el encabezado <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) (desde C11)
1) Copia count caracteres desde el objeto apuntado por src al objeto apuntado por dest . Ambos objetos son interpretados como arrays de unsigned char . Los objetos pueden superponerse: la copia se realiza como si los caracteres se copiaran a un array temporal de caracteres y luego los caracteres se copiaran desde el array a dest .
El comportamiento es indefinido si el acceso ocurre más allá del final del array dest. El comportamiento es indefinido si cualquiera de los punteros dest o src es un puntero inválido o nulo.
2) Igual que (1) , excepto que al detectar los siguientes errores en tiempo de ejecución, pone a cero todo el rango de destino [ dest, dest + destsz ) (si tanto dest como destsz son válidos) y llama a la función constraint handler actualmente instalada:
  • dest o src es un puntero nulo
  • destsz o count es mayor que RSIZE_MAX
  • count es mayor que destsz (ocurriría un desbordamiento de búfer)
El comportamiento es indefinido si el tamaño del array de caracteres apuntado por dest < count <= destsz ; en otras palabras, un valor erróneo de destsz no expone el inminente desbordamiento de búfer.
Como con todas las funciones con verificación de límites, memmove_s solo está garantizada su disponibilidad si __STDC_LIB_EXT1__ está definido por la implementación y si el usuario define __STDC_WANT_LIB_EXT1__ a la constante entera 1 antes de incluir <string.h> .

Contenidos

Parámetros

dest - puntero al objeto destino de la copia
destsz - número máximo de bytes a modificar en el destino (normalmente el tamaño del objeto destino)
src - puntero al objeto fuente de la copia
count - número de bytes a copiar

Valor de retorno

1) Devuelve una copia de dest
2) Retorna cero en caso de éxito y un valor distinto de cero en caso de error. Además, en caso de error, si dest no es un puntero nulo y destsz es válido, escribe destsz bytes cero en el array de destino.

Notas

memmove puede utilizarse para establecer el tipo efectivo de un objeto obtenido mediante una función de asignación.

A pesar de estar especificada "como si" se utilizara un búfer temporal, las implementaciones reales de esta función no incurren en la sobrecarga de doble copia o memoria adicional. Un enfoque común (glibc y bsd libc) es copiar bytes hacia adelante desde el inicio del búfer si el destino comienza antes del origen, y hacia atrás desde el final en caso contrario, con una alternativa al más eficiente memcpy cuando no hay superposición alguna.

Donde strict aliasing prohíbe examinar la misma memoria como valores de dos tipos diferentes, memmove puede utilizarse para convertir los valores.

Ejemplo

#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); // copiar desde [4,5,6] a [5,6,7]
    puts(str);
    // estableciendo el tipo efectivo de la memoria asignada como int
    int* p = malloc(3 * sizeof(int)); // la memoria asignada no tiene tipo efectivo
    int arr[3] = {1, 2, 3};
    memmove(p, arr, 3 * sizeof(int)); // la memoria asignada ahora tiene un tipo efectivo
    // reinterpretando datos
    double d = 0.1;
    // int64_t n = *(int64_t*)(&d); // violación de aliasing estricto
    int64_t n;
    memmove(&n, &d, sizeof d); // OK
    printf("%a es %" PRIx64 " como 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 es mayor que 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
}

Salida posible:

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

Referencias

  • Estándar C23 (ISO/IEC 9899:2024):
  • 7.24.2.2 La función memmove (p: TBD)
  • K.3.7.1.2 La función memmove_s (p: TBD)
  • Estándar C17 (ISO/IEC 9899:2018):
  • 7.24.2.2 La función memmove (p: 264)
  • K.3.7.1.2 La función memmove_s (p: 446)
  • Estándar C11 (ISO/IEC 9899:2011):
  • 7.24.2.2 La función memmove (p: 363)
  • K.3.7.1.2 La función memmove_s (p: 615)
  • Estándar C99 (ISO/IEC 9899:1999):
  • 7.21.2.2 La función memmove (p: 326)
  • Estándar C89/C90 (ISO/IEC 9899:1990):
  • 4.11.2.2 La función memmove

Véase también

copia un búfer a otro
(función)
copia cierta cantidad de caracteres anchos entre dos arreglos, posiblemente superpuestos
(función)
C++ documentation para memmove