【C】内存函数及其模拟实现 —— memcpy | memmove | memcmp

简介: memcpy | memmove | memcmp

@TOC

:star:本文将介绍 内存操作函数,及重点函数的 模拟实现

正文开始@一个人的乐队

1.memcpy

相较于之前介绍过的strcpy只能拷贝字符串,memcpy可以拷贝任意类型,整型浮点型结构体类型等等都可以。
在这里插入图片描述
:green_heart:
在这里插入图片描述
上代码感受它的使用:

#include<stdio.h>
#include<string.h>

int main()
{
    int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int arr2[20] = { 0 };

    //拷贝的是整型数据
    memcpy(arr2, arr1, sizeof(int)* 10);

    int i = 0;
    for (i = 0; i < 20; i++)
    {
        printf("%d ", arr2[i]);
    }
    printf("\n");
    return 0;
}

在这里插入图片描述

:innocent: memcpy的模拟实现 my_memcpy
#include<stdio.h>
#include<assert.h>

void* my_memcpy(void* dest, const void* src, size_t count)
{
    assert(dest&&src);//断言
    void* ret = dest;
    while (count--)
    {
        *(char*)dest = *(char*)src;
        dest = (char*)dest + 1;
        src = (char*)src + 1;
    }
    return ret;
}

int main()
{
    int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int arr2[20] = { 0 };
    my_memcpy(arr2, arr1, sizeof(int)* 10);
    int i = 0;
    for (i = 0; i < 20; i++)
    {
        printf("%d ", arr2[i]);
    }
    return 0;
}

这里有几处小注意,我还是标注在代码旁:
在这里插入图片描述

2.memmove

:star:内存拷贝时,出现重叠现象的时候要用 memmove

:yellow_heart:引例:

若用my_memcpy来完成有重叠的内存拷贝:

#include<stdio.h>

void* my_memcpy(void* dest, const void* src, size_t count)
{
    assert(dest&&src);//断言
    void* ret = dest;
    while (count--)
    {
        *(char*)dest = *(char*)src;
        dest = (char*)dest + 1;
        src = (char*)src + 1;
    }
    return ret;
}

int main()
{
    int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    //这里用的是我刚刚自己模拟实现的函数
    my_memcpy(arr+2, arr, sizeof(int)* 4);

    int i = 0;
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

发现运行结果与预期不符:
在这里插入图片描述
:snowflake:这种情况下,可以从源字符串的末尾下手,从后向前一个一个字节拷:
在这里插入图片描述

:innocent: 模拟实现--- :snowflake:思路 + :snowflake:代码

根据srcdest的位置关系的不同情况,有不同的拷贝方式:
:snowflake:情况一
在这里插入图片描述
:snowflake:情况二
在这里插入图片描述
:snowflake:情况三: 没有重叠内存空间,爱咋拷咋拷
在这里插入图片描述
那么后两种情况可以合并,都采用从源数据的末尾下手,从后往前拷。

#include<stdio.h>
#include<assert.h>

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

int main()
{
    int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    my_memmove(arr+2, arr , 16);
    //my_memmove(arr, arr+2, 16);
    return 0;
}

还是把几个要注意的点标注在代码旁:
在这里插入图片描述

调试:
在这里插入图片描述


拉回到最开始的引例,小边采取了my_memcpy,而没有使用库函数memcpy,是因为vs的memcpy很nb,也可以实现内存重叠的拷贝。
相当于我让你考60分,结果你考了100分,不管怎样,只要完成了内存不重叠的拷贝就算完成任务。
:blue_heart:将来,最好还是,该用memcpy时用memcpy,该用memmove时用memmove.

3.memcmp

:star: 内存比较函数(一个字节一个字节比较)

:green_heart:
在这里插入图片描述
在这里插入图片描述
上代码感受它的使用:

#include<stdio.h>
#include<string.h>

int main()
{
    int arr1[] = { 1, 2, 3, 4, 5 };
    int arr2[] = { 1, 2, 3, 6, 6 };
    int ret = memcmp(arr1, arr2, 13);
    printf("%d\n", ret);
    return 0;
}

在这里插入图片描述

相关文章
|
10天前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
25 3
|
2天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
11天前
|
C语言 C++
c语言回顾-内存操作函数
c语言回顾-内存操作函数
34 0
|
3月前
|
存储 分布式计算 Hadoop
HadoopCPU、内存、存储限制
【7月更文挑战第13天】
249 14
|
2月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
260 0
|
1天前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
5天前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
10天前
|
存储 编译器
数据在内存中的存储
数据在内存中的存储
29 4
|
8天前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
24 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
16天前
|
存储 机器学习/深度学习 人工智能
数据在内存中的存储
数据在内存中的存储