浅析memmove函数之内存重叠
2018-02-07 11:07
162 查看
话说上一节说到memcpy函数实现没有考虑内存重叠问题,难道C库函数故意留一个bug吗?当然不是了,memmove函数就弥补了这个不足哦,是不是以前一直觉得这两个函数没啥区别呢,实际上区别大了去了,下面详细道来。
老话常谈,C语言中操作内存的最小单元当属字节,假如100个字节的内存需要搬运,恰巧的是目的内存的100字节中,包含了源地址中的50个,假如依旧按照memcpy方式来的话,保证那50个字节重叠部分不是你想要的,不信就弄一个100字节的数组试一试喽。
图中展示了两种内存重叠的情况,乍一看还挺复杂,如何快速识破他的真面目呢?其实,搞清楚两点,一切反动派都是纸老虎,哈哈
内存是否重叠 做减法
内存地址间距(src-dst)能否装下count字节,装不下的话,src拷贝后肯定会占用dst的部分内存啦,这里只需做减法,比大小,不看正负
拷贝过程 看方向
搬砖工从src位置一块砖一块砖的搬到dst位置,从src到dst这个方向与内存增长方向一致,那完了,搬着石头砸自己的脚,肯定破坏了自己的内容,脚疼啊。若二者方向相反,src已经搬完了,腾空了内存,正好供dst用啊,不重叠喽,感觉说的好啰嗦,有助理解吧,对应图例,图一重叠但不影响搬运内容,图二重叠但影响内容,我们memmove函数致力于解决这个问题。
面对上图中内存重叠的情况,我们需要对这种情况进行判断,然后针对拷贝方向与内存增长方向一致的情况做出讨论和处理,怎么处理呢?再想想我们的两条原则,第一条原则内存的相对位置我们可改变不了,也就是间距,这是固定的。好吧那就只有改变第二条了,第二条什么来着,方向,方向,方向,重要的说三遍。
好吧,方向怎么改呢?内存方向?那改屁啊,内存自诞生起就定好的,那就只能改他了,哈哈哈,拷贝方向,长话短说,我先拷贝src的最高字节到dst的最高字节,依次拷次高字节,就是反着拷,来看具体实现:
哈哈,一气呵成,细细思考这些细节,还是耐人寻味的,这就是C语言的魅力吧,换个思路,每个细胞里面都包含了母体的全部信息,一叶知秋,希望能够通过这些细致的思考,迅速提示对C语言的深入认识喽
老话常谈,C语言中操作内存的最小单元当属字节,假如100个字节的内存需要搬运,恰巧的是目的内存的100字节中,包含了源地址中的50个,假如依旧按照memcpy方式来的话,保证那50个字节重叠部分不是你想要的,不信就弄一个100字节的数组试一试喽。
1. 内存重叠原理分析
这里借用一个图来用一下,图上有该作者的链接,有兴趣者可以访问哦,替他打一波广告。图中展示了两种内存重叠的情况,乍一看还挺复杂,如何快速识破他的真面目呢?其实,搞清楚两点,一切反动派都是纸老虎,哈哈
内存是否重叠 做减法
内存地址间距(src-dst)能否装下count字节,装不下的话,src拷贝后肯定会占用dst的部分内存啦,这里只需做减法,比大小,不看正负
拷贝过程 看方向
搬砖工从src位置一块砖一块砖的搬到dst位置,从src到dst这个方向与内存增长方向一致,那完了,搬着石头砸自己的脚,肯定破坏了自己的内容,脚疼啊。若二者方向相反,src已经搬完了,腾空了内存,正好供dst用啊,不重叠喽,感觉说的好啰嗦,有助理解吧,对应图例,图一重叠但不影响搬运内容,图二重叠但影响内容,我们memmove函数致力于解决这个问题。
2. memmove函数原型
先看函数原型吧,好眼熟,跟memcpy一摸一样呀,难道眼花了,没错就是一样。void* my_memmove(void* dst, const void* src, unsigned int size)
面对上图中内存重叠的情况,我们需要对这种情况进行判断,然后针对拷贝方向与内存增长方向一致的情况做出讨论和处理,怎么处理呢?再想想我们的两条原则,第一条原则内存的相对位置我们可改变不了,也就是间距,这是固定的。好吧那就只有改变第二条了,第二条什么来着,方向,方向,方向,重要的说三遍。
好吧,方向怎么改呢?内存方向?那改屁啊,内存自诞生起就定好的,那就只能改他了,哈哈哈,拷贝方向,长话短说,我先拷贝src的最高字节到dst的最高字节,依次拷次高字节,就是反着拷,来看具体实现:
void *memmove(void *dest,void *src,unsigned int size) { char *d=(char *)dest; //牛鬼蛇神都得转存成字节,字节是最基本拷贝单元呢 char *s=(char*)src; //源地址和目的地址都得转,别忘了 if(d==NULL||s==NULL||size<0) return NULL; //给我空地址,我可不要,扔回去 if(s<d&&s+size>d){ //两个条件,方向和间距喽 s=s+size-1; //这个是重叠第二种情况,需要调整拷贝方向 d=d+size-1; //把指针指向需要拷贝的最末字节(以前是最开始字节) while(size--) *d--=*s--; //搬一个减一个地址,直到完成所有拷贝 }else{ while(size--) *d++=*s++; //这是第一种情况,及不重叠的情况哦 } return dest; }
哈哈,一气呵成,细细思考这些细节,还是耐人寻味的,这就是C语言的魅力吧,换个思路,每个细胞里面都包含了母体的全部信息,一叶知秋,希望能够通过这些细致的思考,迅速提示对C语言的深入认识喽
相关文章推荐
- 避免内存重叠的memmove()函数
- C++实现内存复制函数(memmove解决内存重叠)
- memmove函数与内存重叠
- memmove()函数:复制内存内容(优点:可以处理重叠的内存块)
- memmove函数如何考虑内存重叠的
- 内存操作函数memcpy和memmove
- 内存操作函数memcpy,memccpy,memmove,memchr,memcmp,memicmp,memset
- 模拟实现字符串操作函数(strcpy,strstr,strcat,strcmp,strlen)与内存操作函数(memcpy,memmove)
- C语言 编写函数实现内存重叠拷贝,不允许调用memmove函数
- memmove 和 memcpy的区别以及处理内存重叠问题
- [整理]内存重叠之memcpy、memmove
- 避免内存重叠memmove()性能
- 自己实现内存操作函数memset(),memcmp(),memcpy(),memmove()
- strcpy,memcpy,memmove和内存重叠分析
- strcpy,memcpy,memmove的内存重叠
- 实例介绍利用valgrind定位memcpy内存重叠问题------顺便再次说说memcpy和memmove的区别
- 浅析C语言之内存分配函数malloc()、realloc()、calloc()
- 内存操作函数memcpy,memccpy,memmove,memchr,memcmp,memicmp,memset
- memmove 和 memcpy的区别以及处理内存重叠问题
- 2.C语言实现函数void *memmove(void *dest, const void *src, size_t n)。memmove 函数的功能是拷贝src所指的内存内容前n个字节到dest所指