Why copy using pointers in loop:
for (int i = 0; i < size; i++) {
dst[i] = src[i];
}
is not the same as memmove?:
memmove(dst, src, size);
When we have overlap between src and dst?
Why copy using pointers in loop:
for (int i = 0; i < size; i++) {
dst[i] = src[i];
}
is not the same as memmove?:
memmove(dst, src, size);
When we have overlap between src and dst?
Your copying code may change some of the source elements before they are copied. The output of this code:
#include <stdio.h>
#include <string.h>
static void Copy(char *dst, const char *src, size_t size)
{
for (int i = 0; i < size; ++i)
dst[i] = src[i];
}
int main(void)
{
char b0[3] = { 'A', 'B', 'C' };
char b1[3] = { 'A', 'B', 'C' };
memmove(b0+1, b0+0, 2);
printf("After memmove: b0[1] = %c, b0[2] = %c.\n", b0[1], b0[2]);
Copy(b1+1, b1+0, 2);
printf("After Copy: b1[1] = %c, b1[2] = %c.\n", b1[1], b1[2]);
}
is:
After memmove: b0[1] = A, b0[2] = B. After Copy: b1[1] = A, b1[2] = A.
because, when i
is 0, dst[0]
is b1[1]
, so b1[1]
is overwritten with 'A'
before the loop increments i
to 1. Then, when i
is 1, src[1]
is b1[1]
, which now contains 'A'
instead of its original 'B'
, so the data copied to dst[1]
is 'A'
and not 'B'
.
When we have overlap between src and dst?
If you want an example:
char str[] = "Hello world"
memmove(str, str + 6, strlen(str + 6) + 1);
It removes "Hello "
from the str
. Destination and source are overlapping.
Apart from the boring bug memmove(dst, src, size);
-> memmove(dst, src, sizeof(*dst) * size);
, then:
memmove
specifically gives this guarantee (C23 7.26.2.3)
void *memmove(void *s1, const void *s2, size_t n);
The
memmove
function copiesn
characters from the object pointed to bys2
into the object pointed to bys1
. Copying takes place as if then
characters from the object pointed to bys2
are first copied into a temporary array ofn
characters that does not overlap the objects pointed to bys1
ands2
, and then then
characters from the temporary array are copied into the object pointed to bys1
.
Because memmove
comes with this extra safety, it is slower than memcpy
and should only be used in situations where you know or suspect that objects overlap.
A plain loop as in your example is similar to memcpy
, except in your loop you actually can know that dst
and src
aren't overlapping. memcpy
cannot know that internally.
memmove()
chooses what direction to use when copying so that you're not copying a copy (of a copy (of a copy (...)). Your loop always copies from low address to high address. See ideone.com/xymcuh – pmg Commented Jan 30 at 11:19dst=src+1
. The loop will plaster the first value over all the rest, while memmove... won't. – teapot418 Commented Jan 30 at 11:22dst
andsrc
are pointers to. – Ted Lyngmo Commented Jan 30 at 11:37