memcpy 和 memmove 都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下: void *memcpy(void *dst, const void *src, size_t count); void *memmove(void *dst, const void *src, size_t count); 他们的作用是一样的,唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确。
第一种情况下,拷贝重叠的区域不会出现问题,内容均可以正确的被拷贝。 第二种情况下,问题出现在右边的两个字节,这两个字节的原来的内容首先就被覆盖了,而且没有保存。所以接下来拷贝的时候,拷贝的是已经被覆盖的内容,显然这是有问题的。 实际上,memcpy只是memmove的一个子集。 memmove在copy两个有重叠区域的内存时可以保证copy的正确,而memcopy就不行了,但memcopy比memmove的速度要快一些,如: char s[] = "1234567890"; char* p1 = s; char* p2 = s+2;
memcpy(p2, p1, 5)与memmove(p2, p1, 5)的结果就可能是不同的,memmove()可以将p1的头5个字符"12345"正确拷贝至p2,而memcpy()的结果就不一定正确了 关于memmove的实现:
void *mymemmove(void *dest, const void *src, size_t n)
{
char temp[n];
int i;
char *d = dest;
const char *s = src;
for (i = 0; i < n; i++)
temp[i] = s[i];
for (i = 0; i < n; i++)
d[i] = temp[i];
return dest;
}
关于memcpy的实现:
void *mymemcpy(void *dest, const void *src, size_t n)
{
char *d = dest;
const char *s = src;
int *di;
const int *si;
int r = n % 4;
while (r--)
*d++ = *s++;
di = (int *)d;
si = (const int*)s;
n /= 4;
while (n--)
*di++ = *si++;
return dest;
}
下面再通过一个例子进行描述:
#include <string.h>
void *memmove2(void *dest, const void *src, size_t n)
{
char temp[n];
int i;
char *d = dest;
const char *s = src;
for (i = 0; i < n; i++)
temp[i] = s[i];
for (i = 0; i < n; i++)
{
d[i] = temp[i];
printf("the src is %s\n", src);
printf("the dest is %s\n", dest);
printf("the temp is %s\n", temp);
}
return dest;
}
void *memcpy2(void *dest, const void *src, size_t n)
{
char *d = dest;
const char *s = src;
int *di;
const int *si;
int r = n % 4;
while (r--)
*d++ = *s++;
di = (int *)d;
si = (const int*)s;
n /= 4;
while (n--)
*di++ = *si++;
return dest;
}
int
main(int argc, char **argv)
{
char s[] = "1234567890";
char* p1 = s;
char* p2 = s+2;
char s1[] = "1234567890";
char* p11 = s1;
char* p21 = s1+2;
memcpy2(p2, p1, 5);
memmove2(p21, p11, 5);
printf("the p2 is %s\n", p2);
printf("the p1 is %s\n", p1);
printf("the s is %s\n", s);
printf("the p21 is %s\n", p21);
printf("the p11 is %s\n", p11);
printf("the s1 is %s\n", s1);
return 0;
}
输出结果为:
the src is 1214567890
the dest is 14567890
the temp is 12345
the src is 1212567890
the dest is 12567890
the temp is 12345
the src is 1212367890
the dest is 12367890
the temp is 12345
the src is 1212347890
the dest is 12347890
the temp is 12345
the src is 1212345890
the dest is 12345890
the temp is 12345
the p2 is 12145890
the p1 is 1212145890
the s is 1212145890
the p21 is 12345890
the p11 is 1212345890
the s1 is 1212345890
这里边memcpy确实发生了错误,由于是发生了重叠,其次memcpy又是对于部分数据以其他形式进行赋值,所以在一定情况下,结果就不一定正确了。