Escriba su propio memcpy() y memmove()

La función memcpy se utiliza para copiar un bloque de datos desde una dirección de origen a una dirección de destino. A continuación se muestra su prototipo.

void * memcpy(void * destination, const void * source, size_t num);

La idea es simplemente encasillar las direcciones dadas en char * (char toma 1 byte). Luego, uno por uno, copie los datos desde el origen hasta el destino. A continuación se muestra la implementación de esta idea. 

C

// A C implementation of memcpy()
#include<stdio.h>
#include<string.h>
 
void myMemCpy(void *dest, void *src, size_t n)
{
// Typecast src and dest addresses to (char *)
char *csrc = (char *)src;
char *cdest = (char *)dest;
 
// Copy contents of src[] to dest[]
for (int i=0; i<n; i++)
    cdest[i] = csrc[i];
}
 
// Driver program
int main()
{
char csrc[] = "GeeksforGeeks";
char cdest[100];
myMemCpy(cdest, csrc, strlen(csrc)+1);
printf("Copied string is %s", cdest);
 
int isrc[] = {10, 20, 30, 40, 50};
int n = sizeof(isrc)/sizeof(isrc[0]);
int idest[n], i;
myMemCpy(idest, isrc, sizeof(isrc));
printf("\nCopied array is ");
for (i=0; i<n; i++)
    printf("%d ", idest[i]);
return 0;
}

Producción:

Copied string is GeeksforGeeks
Copied array is 10 20 30 40 50

Complejidad de tiempo: O(n)

Espacio Auxiliar: O(1)

¿Qué es memmove() ?

memmove() es similar a memcpy() ya que también copia datos de un origen a un destino. memcpy() genera problemas cuando las direcciones de origen y destino se superponen, ya que memcpy() simplemente copia los datos uno por uno de una ubicación a otra. Por ejemplo, considere el siguiente programa. 

C

// Sample program to show that memcpy() can lose data.
#include <stdio.h>
#include <string.h>
int main()
{
char csrc[100] = "Geeksfor";
memcpy(csrc+5, csrc, strlen(csrc)+1);
printf("%s", csrc);
return 0;
}

Producción:

GeeksGeeksfor

Dado que las direcciones de entrada se superponen, el programa anterior sobrescribe la string original y provoca la pérdida de datos. 

C

// Sample program to show that memmove() is better than memcpy()
// when addresses overlap.
#include <stdio.h>
#include <string.h>
int main()
{
char csrc[100] = "Geeksfor";
memmove(csrc+5, csrc, strlen(csrc)+1);
printf("%s", csrc);
return 0;
}

Producción:

GeeksGeeksfor

¿Cómo implementar memmove()?

El truco aquí es usar una array temporal en lugar de copiar directamente de src a dest. El uso de la array temporal es importante para manejar los casos en los que las direcciones de origen y destino se superponen. 

C

//C++ program to demonstrate implementation of memmove()
#include<stdio.h>
#include<string.h>
 
// A function to copy block of 'n' bytes from source
// address 'src' to destination address 'dest'.
void myMemMove(void *dest, void *src, size_t n)
{
// Typecast src and dest addresses to (char *)
char *csrc = (char *)src;
char *cdest = (char *)dest;
 
// Create a temporary array to hold data of src
char *temp = new char[n];
 
// Copy data from csrc[] to temp[]
for (int i=0; i<n; i++)
    temp[i] = csrc[i];
 
// Copy data from temp[] to cdest[]
for (int i=0; i<n; i++)
    cdest[i] = temp[i];
 
delete [] temp;
}
 
// Driver program
int main()
{
char csrc[100] = "Geeksfor";
myMemMove(csrc+5, csrc, strlen(csrc)+1);
printf("%s", csrc);
return 0;
}

Producción:

GeeksGeeksfor

Complejidad de tiempo: O(n)

Espacio Auxiliar: O(1)

Optimizaciones:El algoritmo es ineficiente (y honestamente duplica el tiempo si usa una array temporal). Deben evitarse las copias dobles a menos que sea realmente imposible. En este caso, sin embargo, es posible evitar copias dobles eligiendo una dirección de copia. De hecho, esto es lo que hace la función de biblioteca memmove(). Al comparar las direcciones src y dst, debería poder encontrar si se superponen. – Si no se superponen, puede copiar en cualquier dirección. – Si se superponen, encuentre qué extremo del destino se superpone con el origen y elija la dirección de la copia en consecuencia. – Si el principio del destino se superpone, copie de principio a fin – Si el final del destino se superpone, copie de principio a fin – Otra optimización sería copiar por tamaño de palabra. Solo tenga cuidado de manejar las condiciones de contorno. – Una optimización adicional sería usar instrucciones vectoriales para la copia ya que son contiguas. Este artículo es una contribución de Saurabh Jain. Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *