关于c:memmove-和-memcpy的区别

49次阅读

共计 2039 个字符,预计需要花费 6 分钟才能阅读完成。

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 的一个子集。

二者的 c 语言实现很简略,有趣味的敌人能够去看看。在理论状况下,这两个函数都是用汇编实现的。

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()的后果就不肯定正确了

变态的命名

咱们在写程序时,个别考究见到变量的命名,就能让他人根本晓得该变量的含意。memcpy 内存拷贝,没有问题;memmove,内存挪动?错,如果这样了解的话,那么这篇文章你就必须要好好看看了,memmove 还是内存拷贝。那么既然 memcpy 和 memmove 二者都是内存拷贝,那二者到底有什么区别呢?

先说 memcpy

你有没有好好的加入过一场 C ++ 口试。让你写出 memcpy 的实现,这是如许常见的口试题啊。当初,拿起你的演算纸和笔; 是的,是笔和纸,不是让你在你的 IDE 上写。写不进去?看上面吧:

void  *memcpy(void *dest, const void *src, size_t count)
{assert(dest != NULL || src != NULL);

char *tmp = (char *)dest;
char *p = (char *)src;

while (count--)
{*tmp++ = *p++;}
return dest;
}

memcpy 的实现很简略,个别在口试时,呈现写源码的题目,无非就是须要留神以下几点:

1. 确定函数原型;
2. 判断参数合法性;
3. 逻辑实现(思考各种状况,统称逻辑实现);
4. 错误处理。

当然了,我的这个没有错误处理,也不须要错误处理。下面,我写出了 memcpy 的实现源码,实现原理如下图所示:

这样上来,下面的代码会运行的很好,如果呈现上面的状况呢?

i、n、k 的内存和 J、e、l 的内存地址重合了,当初再应用下面的代码进行 copy 时,会呈现什么问题呢?你有没有想过这个问题。如果没有,那就当初想想,不急着浏览上面的内容。

而后,我再留一个问题,下面的代码中,为什么都须要将 void 转换成 char 呢?比方:
char *tmp = (char *)dest;

再说 memmove

memmove 也是用来实现内存的间接拷贝的。说起这个命名,我集体觉的多少还是有点坑的。既然 memmove 也是用来内存数据挪动的,那就先来看看 memmove 的实现源码。

void *memmove(void *dest, const void *src, size_t count)
{assert(dest != NULL || src != NULL)

if (dst < src)
{char *p = (char *)dest;
char *q = (char *)src;
while (count--)
{*p++ = *q++;}
}
else
{char *p = (char *)dest + count;
char *q = (char *)src + count;
while (count--)
{*--p = *--q;}
}

return dest;
}

从源码看,memmove 确实比 memcpy 简单一些; 再认真一看,多了些什么?哦,多了一个 else 分支,而正是这个 else 分支,就解决了当 src 和 dest 的内存重合的问题。

memcpy 和 memmove 的比拟

从实现源码中确实能看出一些猫腻,当呈现了 src 和 dest 的内存有重合的机会时,memmove 的解决规定是从后往前进行 copy。当然了,重合的问题,须要思考的以下两种场合。

如图所示,当呈现 (1) 对应的状况时,就须要先从 src 的头部开始复制; 也就是 memmove 源码中的 if 分支,这部分源码和 memcpy 的实现是统一的; 当呈现 (2) 对应的状况时,就须要先从 src 的尾部开始复制,防止出现了笼罩景象。这就是 memmove 比 memcpy 多的一个思考点,所以说,在理论应用时,应用 memmove 是比 memcpy 更平安的。

正文完
 0