4.a Memcpy, memmove y memcmp

memcpy, memmove y memcmp son funciones en el lenguaje de programación C que trabajan con memoria y se utilizan para realizar diferentes operaciones relacionadas con arreglos de bytes. A continuación daremos una breve descripción de cada una:

  1. memcpy (Memory Copy):
    • Uso: void *memcpy(void *dest, const void *src, size_t n);
    • Descripción: memcpy se utiliza para copiar un bloque de memoria desde una ubicación de origen (src) a una ubicación de destino (dest) en la memoria. Copia un número específico de bytes (n) desde la ubicación de origen a la ubicación de destino.
    • Importante: memcpy no verifica si las áreas de memoria de origen y destino se superponen. Por lo tanto, si las áreas de memoria se superponen, el comportamiento es indefinido.
  2. memmove (Memory Move):
    • Uso: void *memmove(void *dest, const void *src, size_t n);
    • Descripción: memmove se utiliza para copiar un bloque de memoria desde una ubicación de origen (src) a una ubicación de destino (dest) en la memoria, similar a memcpy. La diferencia principal es que memmove garantiza que los datos se copiarán correctamente incluso si las áreas de memoria de origen y destino se superponen. Esto lo hace más seguro cuando trabajas con datos superpuestos.
    • Importante: memmove puede ser un poco más lento que memcpy debido a la necesidad de manejar la superposición de memoria.
  3. memcmp (Memory Compare):
    • Uso: int memcmp(const void *s1, const void *s2, size_t n);
    • Descripción: memcmp se utiliza para comparar dos bloques de memoria (s1 y s2) de igual longitud (n) byte a byte. Devuelve un valor entero que indica si los bloques son iguales, y si no lo son, cuál es mayor o menor en función de la comparación de bytes.
    • Valor de retorno: Devuelve un valor negativo si s1 es menor que s2, cero si son iguales y un valor positivo si s1 es mayor que s2.

Estas tres funciones son muy útiles cuando se trabaja con manipulación de memoria en C, pero es importante saber usarlas de manera segura y considerar las implicaciones de rendimiento y comportamiento en caso de superposición de memoria, especialmente al elegir entre memcpy y memmove.


Función memcpy ANSI C

void *memcpy(void *dest, const void *src, size_t n);


Copia los primeros n caracteres del objeto apuntado por src al objeto apuntado por dest.
Valor de retorno:
La función retorna el valor de dest. Si al copiar un objeto al otro se superponen, entonces
el comportamiento no está definido.

#include <stdio.h>
#include <string.h>
int main()
{
 char a[7] = "abcdefg";
 char *ptr;
 int i;
 memcpy( ptr, a, 5 );
 for( i=0; i<7; i++ )
 printf( "a[%d]=%c ", i, a[i] );
 printf( "\n" );
 for( i=0; i<5; i++ )
 printf( "ptr[%d]=%c ", i, ptr[i] );
 printf( "\n" );
 return 0;
}

Yo puedo crear una estructura y hacer una copia de un solo registro como el siguiente ejemplo:

#include <stdio.h>
#include <string.h>

typedef struct{
    int numero;
    char nombre[20];
}Presidente;

int main()
{
    Presidente presi[]={
    {1,"De La Rua"},
    {2,"Nestor Kirchner"},
    {3,"Cristina Fernandez"},
    {4,"Mauricio Macri"}
    };
    Presidente copia;
    memcpy( &copia, &presi[0], sizeof(Presidente) );
    printf( "Presidente: %s\n", copia.nombre );
 return 0;
}

O puedo copiar mas de un registro:

#include <stdio.h>
#include <string.h>

typedef struct{
    int numero;
    char nombre[20];
}Presidente;

int main()
{
    Presidente presi[]={
    {1,"De La Rua"},
    {2,"Nestor Kirchner"},
    {3,"Cristina Fernandez"},
    {4,"Mauricio Macri"}
    };
    Presidente copia[4];
    memcpy( copia, presi, sizeof(Presidente)*4 );  // copia o presi podria haber mandado, se sacan los & porque son arrays y el [0] no va porque ya es la primera posicion
    for (int i=0; i<4; i++)
        printf( "Presidente: %s\n", copia[i].nombre );
 return 0;
}

Función memmove ANSI C

void *memmove(void *dest, const void *src, size_t n);
Copia los primeros n caracteres del objeto apuntado por src al objeto apuntado por
dest.Sin embargo, se asegura de que no estén superpuestos. Por esta razón, copia los
caracteres a un array/arreglo temporalmente. Después vuelve a copiar del array
temporal al objeto en cuestión

Valor de retorno:
La función retorna el valor de s1.

#include <stdio.h>
#include <string.h>
int main()
{
 char a[7] = "abcdefg";
 char *ptr;
 int i;
 memmove( ptr, a, 5 );
 for( i=0; i<7; i++ )
 printf( "a[%d]=%c ", i, a[i] );
 printf( "\n" );
 for( i=0; i<5; i++ )
 printf( "ptr[%d]=%c ", i, ptr[i] );
 printf( "\n" );
 return 0;
}
int main()
{
    int vec[]={1,2,3,4,5};
    memmove(vec, vec+2,sizeof(int)*3);
    for (int i=0; i<5; i++)
        printf( "%d \n", vec[i] );
 return 0;
}

Otro Ejemplo:

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "Hola, Mundo!";

    // Mueve los primeros 5 caracteres al final de la cadena
    memmove(str + 10, str, 5);

    printf("Cadena modificada: %s\n", str);

    return 0;
}

En este ejemplo, estamos moviendo los primeros 5 caracteres de la cadena "Hola, Mundo!" al final de la misma utilizando memmove. Esto funciona de manera segura incluso cuando los bloques de memoria se superponen.


Función memcmp ANSI C

int memcmp(const void *s1, const void *s2, size_t n);
Compara los primeros n caracteres del objeto apuntado por s1 (interpretado como
unsigned char) con los primeros n caracteres del objeto apuntado por s2 (interpretado
como unsigned char).
Valor de retorno:
La función retorna un número entero mayor, igual, o menor que cero, apropiadamente
según el objeto apuntado por s1 es mayor, igual, o menor que el objeto apuntado por
s2.

#include <stdio.h>
#include <string.h>
int main()
{
 char a[3] = { 82, 81, 84 };
 char b[3] = { 85, 83, 86 };
 int i;
 for( i=0; i<3; i++ )
 printf( "a[%d]=%c ", i, a[i] );
 printf( "\n" );
 for( i=0; i<3; i++ )
 printf( "b[%d]=%c ", i, b[i] );
 printf( "\n" );
 i = memcmp( a, b, 4 );
 printf( "a es " );
 if( i < 0 ) printf( "menor que" );
 else if( i > 0 ) printf( "mayor que" );
 else printf( "igual a" );
 printf( " b\n" );
 return 0;
}

Otro Ejemplo:

#include <stdio.h>
#include <string.h>

int main() {
    char str1[] = "Hola";
    char str2[] = "Hola";
    char str3[] = "Holi";

    int result1 = memcmp(str1, str2, strlen(str1));
    int result2 = memcmp(str1, str3, strlen(str1));

    if (result1 == 0) {
        printf("str1 es igual a str2\n");
    } else {
        printf("str1 no es igual a str2\n");
    }

    if (result2 == 0) {
        printf("str1 es igual a str3\n");
    } else {
        printf("str1 no es igual a str3\n");
    }

    return 0;
}

En este ejemplo, estamos utilizando memcmp para comparar las cadenas str1, str2 y str3. Devuelve 0 si las cadenas son iguales en longitud y contenido, y un valor diferente de 0 si son diferentes. En este caso, str1 es igual a str2, pero no es igual a str3.