Implementation of memmove in c language

how to make memmove in c

The memmove function copies n characters from the source to the destination object. In memmove before copying the characters from source to destination object first copied the n character from source to the temporary array, after that copy the n character from the temporary array to the destination object. It prevents the undefined behavior when the source and destination object overlaps.

Note: If source and destination memory overlap with each other then we should use memmove in place of strncpy or memcpy otherwise we may get the undefined result.

Syntax of memmove in C:

void *memmove(void * restrict dst, const void *src, size_t n);

Parameters:

dst— pointer to the destination  object
src— pointer to the source object
n — Number of bytes to copy.

Return value:

The memmove function returns the value of dst.

 

Example of memmove in C,

Let’s see an example code to understand the usage of the memmove() function. In this C code, I am copying the string from an array “src” to the array “dest”.

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

int main ()
{
    char dest[] = "Aticleworld";
    const char src[]  = "Amlendra";

    //Source and destination before memmove
    printf("Before memmove >> dest = %s, src = %s\n\n", dest, src);

    memmove(dest, src, 5);

    //Source and destination after memmove
    printf("After memmove >> dest = %s, src = %s\n\n", dest, src);

    return 0;
}

Output:

memmove in c

 

Some important points related to the memmove in C:

Let’s see some important points related to the memmove function with some examples,

1. If you can guarantee that the source and destination buffer do not overlap, you should use memcpy. If you cannot guarantee that the buffers don’t overlap, you should use memmove. The memcpy function shows undefined behavior with overlapped buffers. Let’s see an example,

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


int main()
{
    char str1[50] = "I am going from Delhi to Gorakhpur";
    char str2[50] = "I am going from Delhi to Gorakhpur";

    //Use of memmove
    printf( "Function:\tmemmove with overlap\n" );

    printf( "Orignal :\t%s\n",str1);

    printf( "Source:\t\t%s\n", str1 + 5 );

    printf( "Destination:\t%s\n", str1 + 11 );

    memmove( str1 + 11, str1 + 5, 29 );

    printf( "Result:\t\t%s\n", str1 );

    printf( "Length:\t\t%d characters\n\n", strlen( str1 ) );


    //Use of memcpy
    printf( "Function:\tmemcpy with overlap\n" );

    printf( "Orignal :\t%s\n",str2);

    printf( "Source:\t\t%s\n", str2 + 5 );

    printf( "Destination:\t%s\n", str2 + 11 );

    memcpy( str2 + 11, str2 + 5, 29 );

    printf( "Result:\t\t%s\n", str2 );

    printf( "Length:\t\t%d characters\n\n", strlen( str2 ) );

    return 0;
}

 

OutPut on X86-64 clang 10.0.0 ( -std- c99):

memcpy vs memmove

 

OutPut on X86-64 clang 9.0.0 ( -std- c99 -O3):

memcpy vs memmove

 

2. The memcpy() function will always be at least as fast as memmove. However, on most platforms, the difference will be minimal.

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

#define BUFFERSIZE  (100 * 1024)  // 100Kb
#define LOOP 10000

int main()
{
    char dest[BUFFERSIZE] = {0};
    char src[BUFFERSIZE] = {0};
    int i = 0;
    double time_spent;
    clock_t start, end;

    //Test memmove function
    //Start clock
    start = clock();
    for ( i = 0; i < LOOP; i++)
    {
        memmove(dest,src,BUFFERSIZE);
    }
    // Recording the end clock tick.
    end = clock();

    // Calculating total time taken by the program.
    time_spent = (double)(end - start) / CLOCKS_PER_SEC;

    printf("memmove() took %f seconds to execute \n", time_spent);


    //Test memcpy function
    //Start clock
    start = clock();
    for ( i = 0; i < LOOP; i++)
    {
        memcpy(dest,src,BUFFERSIZE);
    }
    // Recording the end clock tick.
    end = clock();

    // Calculating total time taken by the program.
    time_spent = (double)(end - start) / CLOCKS_PER_SEC;

    printf("memcpy() took %f seconds to execute \n", time_spent);

    return 0;
}

Output:

Which fast memmove or memmcpy

3. memmove can copy in both forward and backward direction while memcpy only copy in the forward direction. It is the basic difference between memcpy and memmove.

 

How to write own memmove in C?

Your compiler/standard library will likely have a very efficient and tailored implementation of the memmove() function. So if not required avoid creating your own version of the memmove function.

Implementation of the memmove is similar to memcpy but in memmove, we need to handle the overlapping scenario. So here I am creating a temporary array to handle the overlapping scenario.

Here we will copy all n characters in the temp array first, then we will copy the temp array characters in the destination buffer.

void * my_memmove(void* dest, const void* src, unsigned int n)
{
    char *pDest = (char *)dest;
    const char *pSrc =( const char*)src;

    //allocate memory for tmp array
    char *tmp  = (char *)malloc(sizeof(char ) * n);
    if(NULL == tmp)
    {
        return NULL;
    }
    else
    {
        unsigned int i = 0;
        // copy src to tmp array
        for(i =0; i < n ; ++i)
        {
            *(tmp + i) = *(pSrc + i);
        }
        //copy tmp to dest
        for(i =0 ; i < n ; ++i)
        {
            *(pDest + i) = *(tmp + i);
        }
        free(tmp); //free allocated memory
    }
    return dest;
}

 

Let’s create a small application to test our own my_memmove() function.

#include<stdio.h>

void * my_memmove(void* dest, const void* src, unsigned int n)
{
    char *pDest = (char *)dest;
    const char *pSrc =( const char*)src;

    //allocate memory for tmp array
    char *tmp  = (char *)malloc(sizeof(char ) * n);
    if(NULL == tmp)
    {
        return NULL;
    }
    else
    {
        unsigned int i = 0;

        // copy src to tmp array
        for(i =0; i < n ; ++i)
        {
            *(tmp + i) = *(pSrc + i);
        }
        //copy tmp to dest
        for(i =0 ; i < n ; ++i)
        {
            *(pDest + i) = *(tmp + i);
        }
        free(tmp); //free allocated memory
    }

    return dest;
}


int main()
{
    char cSrc[] = "Aticleworld";
    // The destination string size is 14.
    char cDest[16] = {0};

    // copying n bytes of cSrc into cDest
    //Using own my_memcpy function
    my_memmove(cDest, cSrc, 12);

    printf("Copied string: %s\n", cDest);

    int iSrc[] = {10, 20, 30, 40, 50};
    int n = sizeof(iSrc)/sizeof(iSrc[0]);
    int iDest[n], index = 0;

    // copying n bytes of iSrc into iDest
    //Using own my_memcpy function
    my_memmove(iDest, iSrc, sizeof(iSrc));

    printf("\nCopied array is ");
    for (index=0; index<n; index++)
    {
        printf("%d ", iDest[index]);
    }

    return 0;
}

Output:

Copied string: Aticleworld

Copied array is 10 20 30 40 50

 

 

To remove the extra overhead we can also handle the overlapping scenario by putting some condition for source and destination buffer. Let’s see how we can handle the overlapping scenario.

  • If the source and destination addresses are the same then left as it is.
  • If the source and destination addresses overlap then copy from the end (backward copy).

  • If the source and destination addresses do not overlap then copy from the beginning (forward a copy).
void *my_memmove(void *dest, const void *src, unsigned int n)
{
    unsigned char isCopyRequire = 0;  //flag bit
    char *pcSource =(char *)src;
    char *pcDstn =(char *)dest;

    // return if pcDstn and pcSource is NULL
    if ((pcSource == NULL) || (pcDstn == NULL))
    {
        return NULL;
    }
    // overlap buffer
    if((pcSource < pcDstn) && (pcDstn < pcSource + n))
    {
        for (pcDstn += n, pcSource += n; n--;)
        {
            *--pcDstn = *--pcSource;
        }
    }
    else
    {
        while(n--)
        {
            *pcDstn++ = *pcSource++;
        }
    }

    return dest;
}

 

Let’s see create an application to test our own memmove() function,

#include<stdio.h>


void *my_memmove(void *dest, const void *src, unsigned int n)
{
    unsigned char isCopyRequire = 0;  //flag bit
    char *pcSource =(char *)src;
    char *pcDstn =(char *)dest;

    // return if pcDstn and pcSource is NULL
    if ((pcSource == NULL) || (pcDstn == NULL))
    {
        return NULL;
    }
    // overlap buffer
    if((pcSource < pcDstn) && (pcDstn < pcSource + n))
    {
        for (pcDstn += n, pcSource += n; n--;)
        {
            *--pcDstn = *--pcSource;
        }
    }
    else
    {
        while(n--)
        {
            *pcDstn++ = *pcSource++;
        }
    }

    return dest;
}



int main()
{
    char str[50] = "I am going from Delhi to Gorakhpur";

    printf( "Function:\tmy_memmove with overlap\n" );
    printf( "Orignal :\t%s\n",str);
    printf( "Source:\t\t%s\n", str + 5 );
    printf( "Destination:\t%s\n", str + 11 );

    my_memmove( str + 11, str + 5, 29 );

    printf( "Result:\t\t%s\n", str );

    return 0;
}

Output:

implement memmove in C

 

 

We can also create our own memmove using the temporary array but this implementation requires C99 VLAs. Also, it uses temporary storage, there is a much greater risk that it will run out of memory with no warning.

void *my_memmove(void *dest, const void *src, unsigned int n)
{
    unsigned char tmp[n];
    memcpy(tmp,src,n);
    memcpy(dest,tmp,n);
    return dest;
}

 

 

Questions for you, please write answers to these questions in the comment box.

  • How to use and when is good use memmove in C?
  • What’s the proper way to copy an array from a pointer?
  • What is the difference between memmove and memcpy?
  • Which one to use – memmove() or memcpy(), when buffers don’t overlap?

 

Recommended Articles for you:

19 comments

  1. Brilliant explanation sir. I also completed embedded system course and searching job from last 7 month can u plz help me

  2. if(u8CopyByte) {

    while(n–)
    *–pcDstn = *–pcSource;
    }

    return pvDstn;
    }

    That doesn’t work for the case when they don’t overlap. Need to use memcpy() instead of backward copy

Leave a Reply

Your email address will not be published. Required fields are marked *