分类: C/C++
2013-11-01 11:26:07
函数原型:
void *memcpy(void *dest, const void *src, size_t n)
void *memmove(void *dest, const void *src, size_t n)
最近在项目中,郁白在review代码时,建议将memcpy改为memmove,虽然memcpy在我现在的使用场景不会出现问题,但是用memmove总是安全的。记得面试时,日照也问过我这个问题。
两者的功能基本相同,唯一不同的是,当 dest 和 src 有重叠的时候选用不同的函数可能会造成不同的结果。
memcpy的原理是从src的低地址开始到高地址,单个字节复制,如果src与dest有重叠,并行src的地址低于dest的话,将会得不到想要的结果,如果src的址高于dest的话,则不会出现这种情况:
实例:
1 #include
2 #include
3
4 using namespace std;
5
6 int main(void)
7 {
8 int i = 0;
9 int a[10];
10
11 //init
12 for (; i < 10; i ++)
13 {
14 a[i] = i;
15 }
16 //copy
17 memcpy(&a[4], a, sizeof(int) * 6);
18 //output
19 for (i = 0; i < 10; i ++)
20 {
21 cout<<”a["<
22 }
23 return 0;
24 }
输出结果为:
a[0]:0
a[1]:1
a[2]:2
a[3]:3
a[4]:0
a[5]:1
a[6]:2
a[7]:3
a[8]:0
a[9]:1
将第17行改为memmove(&a[4], a, sizeof(int) * 6),结果如下:
a[0]:0
a[1]:1
a[2]:2
a[3]:3
a[4]:0
a[5]:1
a[6]:2
a[7]:3
a[8]:4
a[9]:5
看一下memcpy与memmove的实现
代码:
void* memcpy(void* dest, void* source, size_t count)
{
void* ret = dest;
//memcpy只是简单的字节copy,没有处理重叠的情况
while (count–)
*dest++ = *source;
return ret;
}
void* memmove(void* dest, void* source, size_t count)
{
void* ret = dest;
if (dest <= source || dest >= (source + count))
{
//如果没有重叠或是有重叠重目标地址低于源地址
//从低地址开始复制
while (count –)
*dest++ = *source++;
}
else
{
//有果有重叠且目标地址高于源地址, 这里是高于源地址,不包括等于,有重叠即说明是在中间
//从高地址开始复制
dest += count - 1;
source += count - 1;
while (count–)
*dest– = *source–;
}
return ret;
}