Difference Between memcpy and memmove in C

In the C programming language, both memcpy and memmove are standard library functions used to copy a specified number of bytes from a source memory block to a destination memory block. The fundamental distinction between them lies in how they handle overlapping memory regions. While memcpy assumes that the source and destination do not overlap and results in undefined behavior if they do, memmove guarantees safe copying even when the two buffers share memory addresses.

The Behavior of memcpy

The function signature for memcpy is defined as:

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

In modern C (C99 and later), both pointer arguments are marked with the restrict keyword, which informs the compiler that dest and src point to distinct, non-overlapping memory regions.

Because memcpy assumes independence between the buffers, it typically performs the copy in a single direction (usually from lowest address to highest address). If the destination buffer starts inside the source buffer, copying forward overwrites source data that has not yet been read, leading to data corruption and undefined behavior.

Because it does not perform safety checks or adjust its copy strategy, memcpy can be heavily optimized by compilers using specialized CPU instructions, making it marginally faster than memmove.

The Behavior of memmove

The function signature for memmove is defined as:

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

Unlike memcpy, memmove does not use the restrict keyword and is explicitly designed to handle overlapping memory areas safely. The C standard dictates that memmove must copy the bytes as if they are first copied to a temporary array that does not overlap src or dest, and then copied from that temporary array to dest.

In practice, standard library implementations avoid the overhead of allocating temporary memory. Instead, memmove compares the memory addresses of dest and src to determine the direction of the copy:

  • When dest < src: The destination starts before the source. The function copies bytes sequentially from the beginning to the end (left to right). Even if the end of dest overlaps the start of src, the reading pointer is always ahead of the writing pointer, preventing corruption.
  • When dest > src: The destination starts inside the source. A standard left-to-right copy would overwrite unread source bytes. To prevent this, memmove copies bytes in reverse, starting from the end of the buffers down to the beginning (right to left).

When to Use Each Function

  • Use memcpy when you are certain that the source and destination blocks reside in completely separate memory locations. This is common when copying between two distinct variables, structures, or separately allocated buffers.
  • Use memmove whenever there is a possibility that the memory blocks overlap, such as shifting elements within the same array, implementing sliding windows, or reallocating memory in-place.