pointers-memory · intermediate · ~20 min

Safe overlapping copy (memcpy vs memmove)

Why memmove exists, and how to implement it without UB.

Challenge

Copy n bytes from one memory region to another, getting the right result even when the two regions overlap. This is exactly what the standard memmove guarantees and memcpy does not.

Task

Implement void *my_memmove(void *dst, const void *src, size_t n) that copies n bytes from src to dst and returns dst. The result must be correct even if dst and src overlap. No main — the grader calls it.

Input

dst and src are byte regions (they may overlap, alias, or be disjoint). n is the number of bytes to copy (may be 0).

Output

Returns dst. After the call, dst[0..n-1] holds the original bytes of src[0..n-1].

Example

char buf[10] = "abcdefghij";
my_memmove(buf + 2, buf, 5)   ->   buf becomes "ababcdehij"   (forward overlap)

char buf[10] = "abcdefghij";
my_memmove(buf, buf + 2, 5)   ->   buf becomes "cdefgfghij"   (backward overlap)

Edge cases

  • dst == src (aliased): no-op.
  • n == 0: no-op.
  • Non-overlapping regions: copy either direction; forward is cache-friendly.

Rules

  • Pure C; do not call memcpy or memmove.
  • If dst < src copy forward; if dst > src copy backward — that's what makes overlap safe.

Why this matters

Most C developers learn that memcpy is faster than memmove and use it everywhere — until the day they shift bytes within the same buffer and watch their data corrupt. Implementing memmove's contract by hand cements the difference.

Input format

dst, src (may overlap or alias), and byte count n (may be 0).

Output format

Returns dst; the n bytes from src are copied into it.

Constraints

Pure C. No memcpy / memmove. Handle overlap correctly.

Starter code

#include <stddef.h>
void *my_memmove(void *dst, const void *src, size_t n) { /* TODO */ return dst; }

Common mistakes

Always copying forwards (corrupts when dst > src and they overlap). Comparing dst < src with signed types (use the unsigned pointers as uintptr_t or just unsigned char *).

Edge cases to handle

Aliasing; zero-length copy; one-byte copy.

Complexity

O(n).

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.