手动实现strcpy并考虑内存重叠

在没有内存重叠的风险时的操作如下:

char *strcpy_(char *dst,const char *src)
{
    assert(dst!=NULL&&src!=NULL);  //头文件是#include <cassert>
    char *r=dst;
    while((*dst++ = *src++)!='\0');  //dst指针一直在变,所以要首先保存该指针。
    return r;
}

C语言库函数中关于strcpy:把含有'\0'结束符的字符串复制到另一个地址空间,返回值类型为char *.。src和dst所指内存区域不可以重叠,且dst必须有足够空间来容纳src的字符串。

代码解释:

(1)首先应该检查指针的有效性,查看指针是否为空,这里使用assert。其头文件是#include <cassert>

(2)因为dst指针在变化,而最后需要返回目的地址的起始地址,需要先保存目的地址的起始地址。

(3)一定不要忘记给dst最后的结尾加上'\0',这里由循环的结束条件看出已经自动添加。

(4)返回类型为char *,即dst的原始值。这样可以使函数支持链式表达式,增加了函数的附加值。

int length=strlen(strcpy(strA,strB));

char *strA=strcpy(new char[10],strB);

返回的是dst的原始值,返回src的原始值是没有意义的。而且为了保护原始字符串,已经使用const char *来修饰形参,把const char*作为char *来返回,类型不符。

当出现内存重叠的情况呢?也就是说src的内存区域和dst的内存区域有重叠。

下图说明了所有src和dst内存相对的位置。

手动实现strcpy并考虑内存重叠

上述3种情况依次如下:

(1)src+count<=dst或dst+count<=src即不重叠,这时正常从低字节依次赋值
(2)dst+count>src  这时部分重叠,但不影响赋值拷贝,也可以从低字节开始
(3)src+count>dst  这时也是部分重叠,但影响拷贝,应该从高字节逆序开始。
其实第1种的第二种情况和第二种同属于一类,dst<src即可。
所以其实可以分为2类
(1)src+count<=dst||dst<src
(2)src+count>dst
char *strcpy_imp(char *dst,const char *src,int length)
{
    assert(dst!=NULL&&src!=NULL);
    if(dst<src||src+length<=dst)
    {
        char *s=dst;
        while(length--)
        {
            *dst++=*src++;
        }
        return s;
    }
    else
    {
        dst=dst+length-1;
        src=src+length-1;
        while(length--)
        {
            *dst-- = *src--;
        }
        return ++dst;   //不要忘了++;

    }
}