一、strcpy

strcpy是字符串拷贝函数,将一个字符串拷贝到另一个字符串。

代码:

char *strcpy(char *dst, const char *src) { // [1]
    char *p = dst; // [2]

    if (src == NULL || dst == NULL) { // [3]
        return NULL;
    }

    while ((*dst++ = *src++) != '\0'); // [4]

    return p; // [5]
}

实现该函数的注意点:

  1. 传入参数src使用const修饰,避免函数内部修改数据。
  2. 使用p备份dst指针,在拷贝完成之后返回该值。
  3. 需要判断传入参数的合法性,避免出现不合理输入。
  4. 注意判断拷贝完成的标准是src[i] == '\0','\0'也要拷贝到dst字符串中。
  5. 返回拷贝完成的值,更好的支持链式表达式。

高级:

上面的实现是没有区分内存重叠的场景,假设源目地址存在重叠,使用上面的函数实现是有问题的。如图所示:

image.png

dst和src都是指向同一个数组,当把src的第三个元素赋值到dst后,src原有的'\0'被覆盖了,后续继续拷贝就出现问题。

解决这个问题其实很简单,只要从后往前复制src即可解决这个问题。可参考下面memcpy的实现。

二、memcpy

memcpy的作用是把一块内存区域拷贝到另外一个内存地址上面去。

实现:

void *memcpy(void *dst, const void *src, unsigned int count) { // [1]
    char *pdst, *psrc;

    if (dst == NULL || src == NULL || count == 0) { // [2]
        return NULL;
    }

    if (dst == src) { // [3]
        return dst;
    }

    if (dst > src) { // [4]
        pdst = (char *)dst + count - 1;
        psrc = (char *)src + count - 1;

        while (count--) {
            *pdst-- = *psrc--;
        }
    } else { // [5]
        pdst = (char *)dst;
        psrc = (char *)src;

        while (count--) {
            *pdst++ = *psrc++;
        }
    }

    return dst; // [6]
}

需要注意的点:

  1. src使用const修饰,count设置成无符号类型。
  2. 判断传入参数的有效性,避免无效输入。
  3. 判断源目地址相等的情况。
  4. 目的地址大于源地址,从高位向地位复制,避免出现内存重叠的问题。
  5. 目的地址小于源地址,从低位向高位复制。
  6. 返回复制好的目的地址指针以支持链式表达式。

三、memmove

memmove的作用是把一块内存空间的内容移动到另一个内存空间,实现方法和上面的memcpy一致。

最后修改:2019 年 12 月 08 日
如果觉得我的文章对你有用,请随意赞赏