c语言中模拟实现内存函数memcpy和memmove

目录

前言:

一、memcpy函数的模拟实现

二、memmove的模拟实现:


前言:

之前,我们了解到的字符操作函数应该是最为常见的,比如strcmp,strcpy等函数。但是,这些似乎都有个缺点,只能对字符进行操作,是不是太单一了,而现在我要介绍内存操作函数,是以字节为单位进行操作的。而且函数原型里面的形参都是void类型,也就是说什么类型均可接受,我们来一起看看吧!

一、memcpy函数的模拟实现

首先,这个内存操作函数和strcpy函数很像,只不过一个是操作内存的。我们来看一下这个函数的原型:

void* memcpy(void* dest, const void* src, size_t count)

这里的size_t在64位环境上的话代表了long long unsigned int ,在非64位环境下是long unsigned int。

实际上操作的话如下:

int main()
{
    int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int b[4] = { 5, 6, 1, 2 };

    memcpy(a, b, 16);// 5 6 1 2 5 6 7 8 9 10
    for (int i = 0; i < 10; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

在memcpy传参过程中,a就表示要改数组的首位置,b表示改动数组的首位置,16表示16个字节,也就是说,传的是字节,上述程序中是为了将5 6 1 2传过去,而一个int类型的数据是4个字节,所以就是4 * 4 = 16。

现在重头戏来了:如何模拟实现呢?

既然是一字节一字节修改,我们只需要一个字节一个字节修改即可,从前往后的方式,将void*转化为char*即可,有了思路便可以写出这样的模拟实现的代码:

void* my_memcpy(void* dest, const void* src, size_t count)
{
    //首先进行断言:
    assert(dest && src);

    //存储首位置地址,方便之后好返回
    void* set = dest;

    while (count--)
    {
        *(char*)dest = *(char*)src;
        dest = (char*)dest + 1;
        src = (char*)src + 1;
    }
    return set;
}

这样便可以实现我们的模拟memcpy函数的功能了。

二、memmove的模拟实现:

memmove函数比较特殊,相当于是对memcpy函数的补充。

比如在之前第一段程序里面,如果是传参:(a + 6, a + 5, 16),你以为是1 2 3 4 5 6 6 7 8 9吗?实际上是:1 2 3 4 5 6 6 6 6。究其原因就是这里其实发生了内存重叠,前往后传会把后面的给替换掉,因此出现了错误。

所以,这里就需要重新实现:

先看这个函数的原型:

void* memmove(void* dest, const void*src, size_t count)

与之前的函数原型一致,就表明了,我们要区分传进去的地址是要从前往后传还是从后往前传。

这个很简单,就只需要判断地址谁大谁小即可,所以:

void* my_memmove(void* dest, const void* src, size_t count)
{
    assert(dest && src);
    char* set = dest;
    //后往前
    if (src < dest)
    {
        while (count--)
        {
            *((char*)dest + count) = *((char*)src + count);
        }
    }
    //前往后
    else
    {
        while (count--)
        {
            *((char*)dest) = *((char*)src);
            src = (char*)src + 1;
            dest = (char*)dest + 1;
        }
    }
    return set;
}

完美实现!nice!

继续加油!

你可能感兴趣的:(c语言,c语言,学习)