cmemcpymemmove

memcpy() vs memmove()


I am trying to understand the difference between memcpy() and memmove(). I have read the documentation, that memcpy() doesn't take care of the overlapping source and destination, whereas memmove() does.

However, when I execute these two functions on overlapping memory blocks, they both give the same result. For instance, take the following MSDN example on the memmove() help page:-

Is there a better example to understand the drawbacks of memcpy and how memmove solves it?

// Illustrate overlapping copy: memmove always handles it correctly;
// memcpy may handle it correctly.

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

char str1[7] = "aabbcc";

int main( void )
{
    printf( "The string: %s\n", str1 );
    memcpy( str1 + 2, str1, 4 );
    printf( "New string: %s\n", str1 );

    strcpy_s( str1, sizeof(str1), "aabbcc" );   // reset string

    printf( "The string: %s\n", str1 );
    memmove( str1 + 2, str1, 4 );
    printf( "New string: %s\n", str1 );
}

Output:

memcpy():
The string: aabbcc
New string: aaaabb

memmove():
The string: aabbcc
New string: aaaabb

Solution

  • I'm not entirely surprised that your example exhibits no strange behaviour. Try copying str1 to str1+2 instead and see what happens then. (May not actually make a difference, depends on compiler/libraries.)

    In general, memcpy is implemented in a simple (but fast) manner. Simplistically, it just loops over the data (in order), copying from one location to the other. This can result in the source being overwritten while it's being read.

    memmove does more work to ensure it handles the overlap correctly.

    EDIT:

    (Unfortunately, I can't find decent examples, but these will do). Compare the memcpy and memmove implementations shown here. memcpy just loops, while memmove performs a test to determine which direction to loop in to avoid corrupting the data. These implementations are rather simple. Most high-performance implementations are more complicated (involving copying word-size blocks at a time rather than bytes).