首先看下man的结果:
NAME
memcpy - copy memory area
SYNOPSIS
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
DESCRIPTION
The memcpy() function copies n bytes from memory area src to memory
area dest. The memory areas should not overlap. Use memmove(3) if the
memory areas do overlap.
NAME
memmove - copy memory area
SYNOPSIS
#include <string.h>
void *memmove(void *dest, const void *src, size_t n);
DESCRIPTION
The memmove() function copies n bytes from memory area src to memory
area dest. The memory areas may overlap: copying takes place as though
the bytes in src are first copied into a temporary array that does not
overlap src or dest, and the bytes are then copied from the temporary
array to dest.
可以看到两者最大的区别就是src和dest区域重叠的情况,当重叠时,可以使用memmove。
先看下memcpy的代码:
1: void *memcpy(void *dest, const void *src, size_t n)
2: {
3: void* ret = dest;
4:
5: //从低地址向高地址依次复制
6: while (n--)
7: {
8: *(char*)(dest++) = *(char*)(src++);
9: }
10:
11: return ret;
12: }
而对于重叠的情况:
1.dest地址比src低,可以类似于不重叠即memcpy的方式复制,比如:
1: char a[] = "helloworld";
2: printf("%s\n", a);
3: memcpy(a, a+2, 3);
4: printf("%s\n", a);
从a[2]开始复制3个字符,到a[0]处依次放下。
输出:lloloworld
2.src地址比dest地址低,如果采用memcpy的方式复制,则会出错,比如:
1: char a[] = "helloworld";
2: printf("%s\n", a);
3: memcpy(a+2, a, 3);
4: printf("%s\n", a);
原意是从a[0]开始复制3个字符,到a[2]处依次放下,则为hehelworld
但是输出:hehehworld
正确的代码:
1: void *memmove(void* dest, const void *src, size_t n)
2: {
3: void* ret = dest;
4:
5: if (dest<=src || (char*)dest>= ((char*)src + n))
6: {
7: //当dest地址低于src,或者两者内存区域无重叠
8: while (n--)
9: {
10: *(char*)(dest++) = *(char*)(src++);
11: }
12: }
13: else
14: {
15: //src地址低于dest时
16: //如果仍由低到高复制,dest会覆盖掉src的内容
17: //改为由高地址到低地址复制
18: dest = (char*)dest + n - 1;
19: src = (char*)src + n - 1;
20: while (n--)
21: {
22: *(char*)(dest--) = *(char*)(src--);
23: }
24: }
25:
26: return ret;
27: }
这样调用memove(a+2, a, 3)才是正确的。
输出:hehelworld