【C语言】带你手撕字符函数和字符串函数(3)(内含memcpy、memmove、memcmp函数 )

往期回顾:

【C语言】带你手撕字符函数和字符串函数(1)(内含部分库函数模拟实现)

【C语言】带你手撕字符函数和字符串函数(2)(内含字符串查找函数、字符分类函数等)


本篇文章是字符函数系列的最终章,篇幅不会很长,我们将一起来学习三个常用的内存操作函数:memcpy、memmove和memcmp函数。

话不多说直接上货


1 memcpy

1.1 memcpy的定义

memcpy是用来将源空间中指定大小字节的数据复制到目标空间的函数。定义如下:

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。(注意:这里的num是字节的参数,而不是元素个数的参数)

  • 这个函数遇到'\0'的时候不会停下来

  • 如果source和destination有任何的重叠,复制的结果都是未定义的

为什么在这里,参数destination和source的返回类型是void*类型呢?

这样做可以使这个函数变成通用函数。设计者在设计函数时,并不知道在将来使用这个函数的人会用其复制哪种数据类型,因此在这里统一设置成void*类型。

void*类型也被称为通用类型指针,它的特点是可以接收任意类型数据的地址

1.2 memcpy的模拟实现

既然memcpy是逐个字节拷贝数据,且接受的参数是void*类型,那我们就可以将参数指针通过强制类型转换成char*类型。由于char类型占用大小是一个字节,那么char*指针每次加1就能跳过一个字节。

扫描二维码关注公众号,回复: 14853205 查看本文章
void *my_memcpy(void* dest, const void* src, size_t size)
{
    void* ret = dest;
    while (size--)
    {
        *(char*)dest = *(char*)src;
        dest = (char*)dest + 1;
        src = (char*)src + 1;
    }
    return ret;
}

2 memmove

2.1 memmove的定义

  • memmove其实跟memcpy很像,区别在于memmove处理的源内存块和目标内存块是可以重叠的,而memcpy则不行。

因此,如果遇到源内存块和目标内存块重叠的情况,就用memmove函数处理

2.2 memmove函数的模拟实现

memmove函数模拟的实现较为复杂

void* my_memmove(void* dest, const void* src, size_t size)
{
    void* ret = dest;
    if (dest <= src || (char*)dest >= (char*)src + size)
    {
        while (size--)
        {
            *(char*)dest = *(char*)src;
            dest = (char*)dest + 1;
            src = (char*)src + 1;
        }
    }
    else
    {
        dest = (char*)dest + size - 1;
        src = (char*)src + size - 1;
        while (size--)
        {
            *(char*)dest = *(char*)src;
            dest = (char*)dest - 1;
            src = (char*)src - 1;
        }
    }
    return ret;
}

3 memcmp

3.1 memcmp的定义

  • 函数memcmp比较从ptr1和ptr2两个指针开始的num个字节

  • 返回值如下:

其实memcmp的返回跟strcmp非常相似,只是memcmp不仅仅可以用来比较字符串大小,使用更加灵活

3.2 memcmp的模拟实现

此处可以类比strcmp的模拟实现,稍作修改即可写出memcmp

int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
    assert(ptr1 && ptr2);
    while (num--)
    {
        if (*(char*)ptr1 == *(char*)ptr2)
        {
            ((char*)ptr1)++;
            ((char*)ptr2)++;
        }
        else
            return (*(char*)ptr1 - *(char*)ptr2);
    }
    return 0;
}

至此,字符函数和字符串函数系列结束

猜你喜欢

转载自blog.csdn.net/fbzhl/article/details/129700579