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. Aquí tienes 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 trabajas con manipulación de memoria en C, pero es importante 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 *s1, const void *s2, size_t n);


Copia los primeros n caracteres del objeto apuntado por s2 al objeto apuntado por s1.
Valor de retorno:
La función retorna el valor de s1. 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[0], &presi[0], sizeof(Presidente)*4 );  // copia o presi podria haber mandado
    for (int i=0; i<4; i++)
        printf( "Presidente: %s\n", copia[i].nombre );
 return 0;
}

Función memmove ANSI C

void *memmove(void *s1, const void *s2, size_t n);
Copia los primeros n caracteres del objeto apuntado por s2 al objeto apuntado por
s1.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};
    int vec2[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.