pointers-memory · intermediate · ~25 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.
  • Copy backward when the destination begins inside the source range; otherwise copy forward. Detect overlap using pointer equality within the source range, without ordering unrelated pointers.

Why this matters

Transfer exercise: apply the lesson to a complete function contract.

Input format

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 format

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

Constraints

For n>0 both live byte regions have at least n bytes; overlap is allowed. Return original dst. NULL or n=0 is a no-op in this exercise. No library memcpy/memmove. Do not order unrelated pointers with relational comparisons.

Starter code

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

Common mistakes

Always copying forward or using relational pointer comparison for unrelated objects.

Edge cases to handle

Same pointer; either overlap direction; disjoint allocations; one byte; zero length.

Complexity

O(n).

Background lessons

Up next

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