The memory in memcpy
cannot overlap or you risk undefined behaviour, while the memory in memmove
can overlap.
char a[16];
char b[16];
memcpy(a,b,16); // valid
memmove(a,b,16); // Also valid, but slower than memcpy.
memcpy(&a[0], &a[1],10); // Not valid since it overlaps.
memmove(&a[0], &a[1],10); // valid.
Some implementations of memcpy might still work for overlapping inputs but you cannot count of that behaviour. While memmove must allow for overlapping.