前几天面试,华为的一个技术人员问我一个问题:memcpy和memmove有什么区别?
当时,我没回答上来。我只知道它们的入参和返回值是一样的,区别还不是很清楚,说不上来,我说可能效率不太一样吧。
其实,这两个函数的效率几乎是一样的,区别只是在于内存重叠时,memcpy不能保证拷贝的正确,而memmove却能保证拷贝的正确性。换句话说,memcpy是memmove的子集,memmove更安全。
看一下memcpy的源码:
void *memcpy(void *dest, const void *src, size_t n)
{
const char *s = src;
char *d = dest;
while (n--)
*d++ = *s++;
return dest;
}
再看一下memmove的源码:
void *memmove(void *dest, const void *src, size_t n)
{
const char *s = src;
char *d = dest;
if (d <= s) {
while (n--)
*d++ = *s++;
} else {
d += n;
s += n;
while (n--)
*--d = *--s;
}
return dest;
}
举个简单的例子:
例如 char arr[] = "abcdefghigklmn";
memcpy(arr+2,arr,5); 结果为:arr = "abababahigklmn";
而
memmove(arr+2,arr,5); 结果为:arr = "ababcdehigklmn";
但是:
如果是
memcpy(arr,arr+2,5);
和
memmove(arr,arr+2,5);
则结果都为:arr = "cdefgfghigklmn";
总结一下就是:memcpy是从低地址往高开始拷贝,当dest <= src 时,则两个结果是一样的。而当dest > src时,则memcpy会发生内存重叠,出现拷贝错误。在memmove中,函数会先判断是否dest <= src,当小于时,则执行memcpy,否则,则从高地址向低地址拷贝,防止出现内存重叠发生拷贝错误。
其实,无论在memcpy或memmove,如果都从高地址向低地址拷贝,则都不会出现拷贝错误。所以,memmove没有必要做一个if-else判断,代码非要这样写,可能是展现一下memmove的思路吧,增强可读性吧。
综上,memmove比memcpy更安全,用memcpy的时候,必须考虑区域重叠问题,另外还要考虑缓冲区溢出问题。