Namespaces
Variants

memcpy, memcpy_s

From cppreference.net
< c ‎ | string ‎ | byte
Definido en el encabezado <string.h>
(1)
void * memcpy ( void * dest, const void * src, size_t count ) ;
(hasta C99)
void * memcpy ( void * restrict dest, const void * restrict src, size_t count ) ;
(desde C99)
errno_t memcpy_s ( void * restrict dest, rsize_t destsz,
const void * restrict 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 arreglos de unsigned char .
El comportamiento es indefinido si el acceso ocurre más allá del final del dest array. Si los objetos se superponen (lo cual es una violación del restrict contrato) (desde C99) , el comportamiento es indefinido. El comportamiento es indefinido si dest o src es un puntero inválido o nulo.
2) Igual que (1) , excepto que los siguientes errores se detectan en tiempo de ejecución y provocan que todo el rango de destino [ dest, dest + destsz ) sea puesto a cero (si tanto dest como destsz son válidos), así como llamar 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)
  • los objetos origen y destino se superponen
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, memcpy_s solo está garantizada para estar disponible si __STDC_LIB_EXT1__ está definida 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 origen 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

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

memcpy es la rutina de biblioteca más rápida para copia de memoria a memoria. Normalmente es más eficiente que strcpy , que debe escanear los datos que copia, o memmove , que debe tomar precauciones para manejar entradas superpuestas.

Varios compiladores de C transforman bucles de copia de memoria adecuados a llamadas de memcpy .

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

Ejemplo

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
    // uso 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]);
    // 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};
    memcpy(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;
    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 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:

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

Referencias

  • Estándar C11 (ISO/IEC 9899:2011):
  • 7.24.2.1 La función memcpy (p: 362)
  • K.3.7.1.1 La función memcpy_s (p: 614)
  • Estándar C99 (ISO/IEC 9899:1999):
  • 7.21.2.1 La función memcpy (p: 325)
  • Estándar C89/C90 (ISO/IEC 9899:1990):
  • 4.11.2.1 La función memcpy

Véase también

(C23)
copia un búfer a otro, deteniéndose después del delimitador especificado
(función)
mueve un búfer a otro
(función)
copia cierta cantidad de caracteres anchos entre dos arreglos no superpuestos
(función)