La función memcpy de la biblioteca estándar (string.h) está destinada a copiar una área de memoria byte a byte de un lugar a otro. Es una herramienta versátil para copiar arreglos, estructuras y otros bloques de datos, cuando el rendimiento es importante y no se requieren conversiones de tipo.
Historia de la cuestión:
memcpy apareció junto con la primera implementación de la biblioteca estándar, cuando surgió la necesidad de manejar bloques de memoria "en crudo", por ejemplo, para trabajar con archivos, paquetes de red y serialización de datos. Funciones similares están presentes en casi todos los lenguajes de bajo nivel.
Problema:
memcpy opera solo con bytes, no se preocupa por los tipos de datos, alineación o áreas de memoria superpuestas. Los errores en la especificación del tamaño o en las áreas incorrectas pueden llevar a la corrupción de la memoria o resultados inesperados. Además, usar memcpy para áreas superpuestas provoca un comportamiento indefinido.
Solución:
Usa memcpy solo si estás seguro de que:
memmove.Ejemplo de código:
#include <string.h> typedef struct { int id; float value; } Item; Item src = {42, 3.14f}; Item dest; memcpy(&dest, &src, sizeof(Item)); // copiamos la estructura byte a byte
Características clave:
¿Se puede usar memcpy para copiar cadenas (char)?*
Sí, pero solo si se conoce exactamente la longitud. Si la cadena está terminada en nulo, a menudo se utilizan strcpy o strncpy. Si se confunde el tamaño, es posible que haya un desbordamiento de memoria o pérdida del carácter nulo final.
char src[] = "abc"; char dest[4]; memcpy(dest, src, 4); // Se copian 3 letras + '\0'
¿Qué ocurre al copiar estructuras con alineación no estándar o punteros a través de memcpy?
memcpy no tiene en cuenta la semántica ni los punteros internos. Si una estructura almacena campos dinámicos (por ejemplo, char *buf;), solo se copia la dirección, no el contenido de esa dirección. Esto conduce a lo que se llama una copia "superficial".
typedef struct { char *buf; } Wrapper; Wrapper src = {malloc(10)}; Wrapper dest; memcpy(&dest, &src, sizeof(Wrapper)); // Solo el campo puntero, no el contenido
¿Qué pasará si src y dest se superponen en memcpy?
El comportamiento no está definido por el estándar, puede haber pérdida de datos. Para copiar con superposición, usa memmove:
memmove(dest, src, size); // garantiza una copia correcta
Las matrices se superponen: se aplica memcpy para desplazar parte de la matriz hacia la derecha, src y dest se superponen parcialmente.
Pros:
Contras:
Se utiliza memmove para manejar áreas superpuestas, el volumen de datos se calcula claramente como la cantidad de bytes en la estructura de origen.
Pros:
Contras: