I cannot give a definitive answer, but from what I see of the function descriptions in the various references, the only difference is in how they behave regarding overlapping memory areas; memmove() guarantees that the data will be moved to the
to argument, while memcpy()'s behavior in such instances is undefined.
If I were to speculate, I would assume that the reason that there are two separate functions is due to a combination of efficiency and history. It is clear that regardless of implementation, memcpy() can be written to be more efficient than memmove(); the two obvious ways to implement them is as either an assembly-language block move, if the current system supports one, or as a simple
for loop moving n bytes from array to array one at a time. In the fmorer case, to ensure that it copies correctly, you would have to use a second buffer and copy the data twice (see my solution to the scrolling issue for an example). The x86 version of the block move could also solve the problem by switching the direction flag (see the second solution below), but that's probably more trouble than it's worth.
In the latter case, you can take the same approach, as shown here (code sampled from
True64 Unix C Compiler Reference, modified for ANSI compatibility):
Code: Select all
void *memmove(void *to, const void *from, size_t count) {
char * t1 = to;
const char * t2 = from;
char * t3 = malloc(count);
size_t i;
for(i=0; i<count; i++) t3[i] = t2[i];
for(i=0; i<count; i++) t1[i] = t3[i];
free(t3);
return from;
}
If you wanted to avoid that, you'd need to make sure that any overlapping data is moved first, to avoid overwriting it before it can be moved. Basically, this means that if the
to and
from overlap in a way that
from has a higher address than
to, you would copy starting at the low addresses of
from; while if
to is higher in memory than
from, you would need to copy from the high address in
from, moving downwards in memory. Here's a fairly efficient example of such an implementation (based on a version found in a page entitled
"Unix Incompatibiliy Notes", modified for ANSI compatibility):
Code: Select all
void *memmove(void *to, void *from, size_t count)
{
void *retval = from;
if (from > to)
for ( ; count > 0; count--)
*(to++)= *(from++);
else
for (to+= count-1, from+= count-1; count > 0; count--)
*(to--)= *(from--);
return retval;
}
From what I've read, also, memcpy() predates memmove(), which seems to have been added later when the issue with memcpy()'s handling of overlaps was identified as a problem. I'd assume that memmove() arose out of a specific need, most likely buffer management and scrolling in full-screen text editors, where overlapping areas are the norm rather than the exception. Whatever the origin, it remained rarely used because memcpy() was the established version, and was more efficient in the majority of cases. Mind you, this is speculation on my part; I know, for example, that there is at least one other similar function, bcopy(), which was apparently the standard version on older BSD systems, replacing both memcpy() and memmove(). I don't know what the actual history of them is, off hand.
BTW, given the existence of both malloc() and memcpy() functions, there is one other trivial implementation of memmove():
Code: Select all
void *memmove(void *to, const void *from, size_t count) {
void *buff = malloc(count);
memcpy(buf, from, count);
memcpy(to, buf, count);
free(buf);
return from;
}
HTH. C&CW.