Introduction
Announcements

Schedule
Labs
Assignments
TA office hours

Tests, exam

Topic videos
Some course notes
Extra problems
Lecture recordings

Discussion board

Grades so far

memmove()

This note is an explanation of why memmove() is needed in preference to memcpy() or strcpy() when the source and destination ranges are or might be overlapping (within the same array).

Suppose that you have an array of char of some sufficiently-large size, and it currently contains the bytes "hellogoodbye" (but no terminating \0, in this example — if there is a terminating \0 which you want to keep, you could just adjust the following instructions appropriately).

You have processed the "hello" part, and you want to move the rest of the data to the beginning of the array, so that it now begins "goodbye" (with the rest of the bytes unspecified).

Suppose you have these values:

It might look like what you need is

	strncpy(buf, buf + bytes_to_remove, bytes_in_buf - bytes_to_remove);

However, this is not guaranteed to work.

With the obvious loop to implement strncpy, the above will work. It will assign buf[0] = buf[5], then buf[1] = buf[6], and so on. This will transform

	hellogoodbye
into
	goodbyeodbye
(This might look wrong, but we will of course decrease bytes_in_buf to 7, so only the first seven bytes count, so it's correct. "Move" as used here really means "copy" (this is common in computer programming).)

So, this seems fine. However, the string library functions can be optimized in various ways, usually CPU-specific.

And this means that it doesn't have to move the bytes in order. For example, if it moved the "bye" part of goodbye first (and there might well be a CPU-specific instruction for moving four bytes at a time, meaning that n%4 bytes need to be moved separately), we'd now have

	hellbyeodbye

It now moves the "good" part, i.e. buf[5] through buf[8]:

	yeodbyeodbye

So, this didn't work. That is to say, memcpy and strncpy and strcpy aren't required to move the bytes in the obvious order, so when the source and destination areas overlap they can produce incorrect results.

This is why we need "memmove()". If the source and destination areas might overlap, you must call memmove() to do the moving, not strncpy or memcpy (or strcpy). The rule is that any optimizations in memmove() must not cause the above problem even if the source and destination areas are overlapping. For memcpy and strcpy and strncpy, it is a precondition that the source and destination areas do not overlap (the vastly predominant case), so that the craziest optimizations are possible.

Really, this is another example of the low-level nature of C: You the programmer have to give this information to the string library about whether or not particular optimizations are allowable for this particular copy operation.