memmove函数实现

来源:互联网 发布:php socket 客服系统 编辑:程序博客网 时间:2024/06/06 00:49

背景

memcpy是我们最常用的数据拷贝函数,一般使用不会有啥问题,但是当涉及到目标区域的数据和源数据有数据重叠的时候,可能就会产生我们意想不到的拷贝结果。

究其原因,memcpy是通过从头至尾的顺序拷贝方式实现,所以如果拷贝一开始就导致源数据区的数据被破坏(修改),那么拷贝结果就并不是我们预想到的数据数据拷贝了。

在什么样的情况下会导致memcpy失效呢?这就得追本溯源了,我们知道memcpy的实现方式是顺序拷贝,所以如果在顺序拷贝的过程中,拷贝目标区域的数据地址刚好是还没有拷贝的源数据地址,那么就会出现memcpy失效的情况了。为避免这种情况,可以使用增强的memcpy函数实现,也就是函数memmove,不过我之前也发现过某些编译器的memcpy也修复了这个重叠而失效的错误,不过为了写出更健壮的代码,还是建议大家在需要的时候使用memmove来达到我们的目地。

写这篇文章的目地,是因为以前在面试的时候,当时面试官问我memcpy和memmove的区别。当然,我很easy地说出了他们的区别,但是…估计太紧张了,居然没想起怎么实现memmove,只能含糊不清说出具体原理,真要写代码,木有写出来!现在回想起来,还是自己没有好好总结,充分理解透memmove有效性的情况,因此特地花了点时间重新测试学习了memmove。

附上测试使用的代码。

#include <stdio.h>#include <string.h>void MyMemMove(char *pDst, char *pSrc, size_t tLen);int main(int argc, char **argv){    char pStr[64] = "0123456789abcdefghijklmnopqrstuvwxyz";    char pStr1[64] = "0123456789abcdefghijklmnopqrstuvwxyz";    printf("%s\n", pStr);    MyMemMove(pStr+3, pStr, 5);    memmove(pStr1+3, pStr1, 5);    printf("%s\n%s\ncom:%d\n", pStr, pStr1, strcmp(pStr, pStr1));    return 0;}void MyMemMove(char *pDst, char *pSrc, size_t tLen){    /* 当目标字符串区的头和源字符串区重叠时,需要特殊处理     * 举例:源字符串区:[s,S],目标字符串区:[d,D]     *       s  d    S  D             */    if((pDst>pSrc) && (pDst<(pSrc+tLen)))    {        // 特殊处理        char* p = pSrc + tLen - 1;        char* q = pDst + tLen - 1;        while(p >= pSrc)        {            *q-- = *p--;        }    }    else    {        // 不需要特殊处理可直接用memcpy        memcpy(pDst, pSrc, tLen);    }}
1 0