内存函数​(memcpy、memmove、memset、memcmp)

目录

一、memcpy的使用和实现

使用:

模拟实现: 

二、memmove 使用和模拟实现

模拟实现:

2.1难点:

覆盖拷贝所在的问题

memset的使用

memcmp的函数的使用​

一、memcpy的使用和实现

memcpy 拷贝的就是不重叠的内存。

参数destinationsourcenum
解析存储复制内容的目标空间被拷贝数据源拷贝字节数

void * memcpy ( void * destination, const void * source, size_t num );

// memcpy 可以拷贝任何类型的数据,因此使用 void* 作为参数类型 void* memcpy(void* destination, const void* source, size_t num) 

• 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。

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

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

使用:

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

// 使用 memcpy 将 arr1 中的 4,5,6,7,8 拷贝到 arr2 中

memcpy(arr2, arr1 + 3, 5 * sizeof(int)); // 从 arr1 的第四个元素开始,拷贝 5 个 int 类型的数据到 arr2

for (int i = 0; i < 10; i++) { printf("%d ", arr2[i]);

// 输出 arr2 的内容,预期结果:4 5 6 7 8 0 0 0 0 0 } ;

int main() { char arr1[10] = "he\0o bit";

// 注意:字符串中间有一个 '\0',但实际上 arr1 的内容是:'h', 'e', '\0', 'o', ' ', 'b', 'i', 't', '\0' char arr2[10] = { 0 };

// 使用 memcpy 将 arr1 中的 "o bit" 拷贝到 arr2 中 memcpy(arr2, arr1 + 3, 5);

int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };//将arr1中的1 2 3 4 5 拷贝到arr2中memcpy(arr2, arr1+3, 5 * sizeof(int));int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}int main()
{char arr1[10] = "he\0o bit";char arr2[10] = { 0 };//将arr1中的1 2 3 4 5 拷贝到arr2中memcpy(arr2, arr1 + 3, 5);int i = 0;for (i = 0; i < 10; i++){printf("%c ", arr2[i]);}return 0;
}

模拟实现: 

  void* my_memcpy(void* dest, void* src, size_t num)  
{  
    // 保存目标地址的原始值,这样在函数结束时可以返回它。  
    void* ret = dest; 
    // 确保目标地址和源地址都不是NULL。如果是NULL,则assert会终止程序。  
    assert(dest && src); 
    // 循环,直到拷贝完所有字节。  
    while (num--)  
    {  
        // 从源地址拷贝一个字节到目标地址。  
        *(char*)dest = *(char*)src;  
        // 移动到下一个字节。  
        dest = (char*)dest + 1;  
        src = (char*)src + 1;  
    }  
    // 返回原始的目标地址。  
    return ret;  
}  
int main()  
{  
    // 定义并初始化一个整数数组arr1。  
    int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };  
    // 定义并初始化一个整数数组arr2,所有元素都为0。  
    int arr2[10] = { 0 };  
    // 使用自定义的my_memcpy函数,将arr1中的部分数据拷贝到arr2中。  
   
// 从arr1的第4个元素开始,拷贝5个整数到arr2中。  
    //将arr1中的1 2 3 4 5 拷贝到arr2中  
    my_memcpy(arr2, arr1+3, 5 * sizeof(int));  
}

void* my_memcpy(void* dest, void* src,size_t num)
{void* ret = dest;assert(dest && src);while (num--){*(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[10] = { 0 };//将arr1中的1 2 3 4 5 拷贝到arr2中my_memcpy(arr2, arr1+3, 5 * sizeof(int));int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}

二、memmove 使用和模拟实现

memove 拷贝的就是重叠的内存。

void * memmove ( void * destination, const void * source, size_t num );

返回值说明:返回指向dest的void *指针

参数说明:dest,src分别为目标串和源串的首地址。count为要移动的字节的个数

函数说明:memmove用于从src拷贝count个字节到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。

• 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

• 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

参数destinationsourcenum
解析存储复制内容的目标空间被拷贝数据源拷贝字节数

模拟实现:

2.1难点:
覆盖拷贝所在的问题

我们就要重点注意覆盖拷贝的问题,因为会导致未被拷贝的数值受到更改。

情况一:src在dest之前。

我们可以发现自src下标小端拷贝,就不会出现之前的未进行拷贝就被更改的情况。

情况二:dest在src之前。

我们可以发现自src下标大端拷贝,就不会出现之前的未进行拷贝就被更改的情况。

所以此时我们有了两种选择,按图示来说:

1、在7之前为,前——>后,在7之后,后——>前。

2、在3之前为,前——>后,在3之后,后——>前。

  • my_memmove函数是为了实现内存的移动功能,类似于C标准库中的memmove函数。

  • 这个函数接收三个参数:目标地址、源地址以及需要移动的字节数。 函数开始时,先保存了原始的目标地址,以便最后返回。

  • 通过断言来确保目标地址和源地址都不是NULL。

  • 接下来dest和src的关系,来确定移动的方向。

  • 如果dest< src,说明移动方向是从前往后,因此从源地址的每一个字节拷贝到目标地址,并逐渐向后移动。

  • 如果dest>=src,说明移动方向是从后往前,因此从源地址的最后一个字节开始,逐个拷贝到目标地址的对应位置。最后返回原始的目标地址。

  • main函数中 使用my_memmove函数将arr1的前5个元素移动到从第3个位置开始的位置。这样,数组的前两个位置会被覆盖,而后面的元素则保持不变。

void* my_memmove(void* dest, void* src, size_t num)
{void* ret = dest;assert(dest && src);if (dest < src){//前->后while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else {//后->前while (num--){*((char*)dest + num) = *((char*)src + num);}}return ret;
}int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };//将arr1中的1 2 3 4 5 拷贝到arr2中//my_memcpy(arr1 + 2, arr1, 5 * sizeof(int));my_memmove(arr1 + 2, arr1, 5 * sizeof(int));int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);//1 2 1 2 3 4 5 6 7 8 9 10}return 0;
}

memset的使用

 memset - 内存设置 
void * memset ( void * ptr, int value, size_t num );
memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。

  • 在 main 函数内部,定义了一个字符数组 arr,并初始化为字符串 "hello bit"。注意,数组的大小是10,所以实际上字符串后面还有一个空字符 '\0'。

  • 使用 memset 函数将 arr 的前5个字节设置为字符 'x'。这里的 'x' 实际上会被解释为ASCII码值,所以 'x' 会被设置为每个字节的值。因为 memset 是以字节为单位工作的,所以这里会将 arr 的前5个字节都设置为 'x' 的ASCII值。 打印 arr 的内容。因为 arr 的前5个字节都被设置为了 'x',所以输出将会是 "xxxxx bit"。

int main()
{char arr[10] = "hello bit";memset(arr, 'x', 5);//memset 在设置的时候,是以字节为单位来设置的printf("%s\n", arr);return 0;
}

memcmp的函数的使用​

int memcmp ( const void * ptr1, const void * ptr2, size_t num );
• 比较从ptr1和ptr2指针指向的位置开始,向后的num个字节​

当ptr1<ptr2时,返回值<0

当ptr1=ptr2时,返回值=0

当ptr1>ptr2时,返回值>0

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

  • 定义了两个整数数组 arr1 和 arr2。其中,arr1 包含10个整数(从1到10),而 arr2 包含5个整数(从1到4,然后有一个8)。

  • 使用 memcmp 函数来比较这两个数组的前17个字节。需要注意的是,一个整数通常占用4个字节(这取决于系统和编译器),所以这里实际上比较的是两个数组的前4个整数以及第5个整数的部分字节。 memcmp 函数会返回两个内存区域之间的差异。如果第一个不匹配的字

  • 在 arr1 中的值小于 arr2 中的值,则返回一个负数。如果相等,则返回0。如果 arr1 中的值大于 arr2 中的值,则返回一个正数。

今天就先到这了!!!

看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注!

你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/183080.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux(fork+exec创建进程)

1.进程创建 内核设计与实现43页; 执行了3次ps -f ,ps -f的父进程的ID(PPID)都是一样的,即bash. 实际上Linux上这个bash就是不断的复制自身,然后把复制出来的用exec替换成想要执行的程序(比如ps); 运行ps,发现ps是bash的一个子进程;原因就是bash把自己复制一份,然后替换成ps;…

竞赛选题 题目:基于深度学习的中文对话问答机器人

文章目录 0 简介1 项目架构2 项目的主要过程2.1 数据清洗、预处理2.2 分桶2.3 训练 3 项目的整体结构4 重要的API4.1 LSTM cells部分&#xff1a;4.2 损失函数&#xff1a;4.3 搭建seq2seq框架&#xff1a;4.4 测试部分&#xff1a;4.5 评价NLP测试效果&#xff1a;4.6 梯度截断…

dbeaver连接amabri-hbase

目录 尝试过程 解决之道 总结 尝试过程 注意此章节为记录试错过程&#xff0c;无需跟随操作&#xff0c;仅作试错记录。真正操作方法请看“解决之道”章节 环境ambari安装的hbase2.1.6 使用apche phoenix默认驱动配置 备注&#xff1a;Apache Phoenix 是一个开源的、基于…

fastadmin 如何引入自己的js

在需要的界面中&#xff1a;如何实例说明&#xff1a; 中<script> function zhuruJs(url) { let temp document.createElement( script ); temp.setAttribute( type, text/javascript" );temp.src urL; document.head . appendChild(temp); zhuruJs(location…

ffmpeg 免安装,配置环境变量

1、下载ffmpeg https://download.csdn.net/download/qq284489030/88579595 2、解压 解压ffmpeg-4.4-essentials_build.zip到目标文件夹&#xff0c;比如 d:\apps下&#xff1b; 3、配置环境变量 &#xff08;1&#xff09;电脑桌面鼠标右键点击“此电脑”&#xff0c;弹出…

脚本格式问题记录

服务器上的一些脚本迁移到其他服务上发生的小问题 问题&#xff1a;执行一个在win10系统编写好的shell脚本&#xff0c;放到Linux上执行报错如下&#xff1a; bash: ./xxx.sh: /bin/bash^M: bad interpreter: No such file or directory 原因&#xff1a;window系统写的脚本&a…

iMazing是什么软件?2024最新版本如何下载

iMazing是一款功能强大的iOS设备管理软件&#xff0c;它可以帮助用户备份和管理他们的iPhone、iPad或iPod Touch上的数据。除此之外&#xff0c;它还可以将备份数据转移到新的设备中、管理应用程序、导入和导出媒体文件等。本文将详细介绍iMazing的功能和安全性&#xff0c;并教…

实验一 SAS 基本操作和数据表的导入 2023-11-29

一、上机目的 熟悉SAS的集成环境并掌握它的基本操作。理解SAS程序的结构&#xff0c;理解其中的过程&#xff0c;过程选项&#xff0c;语句&#xff0c;语句选项等概念&#xff0c;掌握SAS编程技术。 二、上机内容 主要有SAS操作界面、SAS窗口操作、SAS菜单操作、SAS按钮操作…

用函数初始化数组

将数组全部初始化为相同值 对于一般情况 一般是用函数&#xff0c;传什么数就初始化为什么数 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> void init(int arr[], int len, int num) {int i;for (i 0; i < len; i){arr[i] num;} } int main() {int arr[…

如何判断哪种屋顶适合安装光伏板?

随着国家对可再生能源的推广和大力发展&#xff0c;光伏板开始被越来越多人所熟知。而将光伏板安装在家庭楼顶上&#xff0c;不仅可以有效节省土地和楼房面积&#xff0c;还能够为家庭提供更多的经济和环保效益&#xff0c;成为了越来越多人的选择。哪种屋顶适合安装光伏板呢&a…

php爬虫实现把目标页面变成自己的网站页面

最近又被烦的不行&#xff0c;琐事不断&#xff0c;要是比起懒来一个人比一个人懒&#xff0c;但是懒要转换成动力啊&#xff0c;能让自己真正的偷懒&#xff0c;而不是浪费时间。每天还是需要不断的学习的&#xff0c;才能更好的提高效率&#xff0c;把之前做的简单小功能爬虫…

第二部分 系统管理篇

文件和目录管理 Linux基础 在Linux操作系统中&#xff0c;一切都是文件。Linux文件是区分大小写的。 Linux文件的拓展名和它的种类没有任何关系 Linux的目录结构为树状结构&#xff0c;顶级的目录为根目录“/”。 文件类型 用file命令查看文件类型 文件操作命令 1.mkdir创…

el-select实现分屏效果

动态绑定class值 &#xff0c;多种判断 :class"type 8 ? home-stye-2 : type 24 ? home-stye-1 : home-stye-3" <div class"home-right-top"><div class"home-right-top-video"><el-row :gutter"20"><el-c…

Android进阶之路 - TextView文本渐变

那天做需求的时候&#xff0c;遇到一个小功能&#xff0c;建立在前人栽树&#xff0c;后人乘凉的情况下&#xff0c;仅用片刻就写完了&#xff1b;说来惭愧&#xff0c;我以前并未写过文本渐变的需求&#xff0c;脑中也仅有一个shape渐变带来的大概思路&#xff0c;回头来看想着…

福州大学《嵌入式系统综合设计》 实验九:ROI视频编码

一、实验目的 ROI视频编码即感兴趣区域视频编码&#xff0c;即针对感兴趣区域进行重点编码&#xff0c;提高编码质量&#xff0c;而对非感兴趣区域采用低质量编码。通过这种方法可以降低码率。本实验即让同学们能够在算能的FFMPEG接口下实现基于ROI的视频编码。 二、实验内容…

离散化笔记

文章目录 离散化的适用条件离散化的意思AcWing 802. 区间和CODECODE2 离散化的适用条件 离散化用于区间求和问题对于数域极大&#xff0c;而数的量很少的情况下 离散化的意思 背景&#xff1a;对于一个极大数域上的零星几个数进行操作后&#xff0c;求某段区间内的和 其实意思…

JSch线上出现com.jcraft.jsch.JSchException: channel is not opened.问题分析

JSch线上出现com.jcraft.jsch.JSchException: channel is not opened.问题分析 文章目录 JSch线上出现com.jcraft.jsch.JSchException: channel is not opened.问题分析1. 背景1.系统使用jsch这个框架做文件发送以及远程命令执行的操作,系统一直运行正常,直到某一个环境发现 2.…

关于我司在上海物联网行业协会展厅展示项目案例

1 项目背景 上海市物联网行业协会&#xff08;SIOT&#xff09;是由本市物联网行业同业企业及其他相关经济组织自愿组成、实行行业服务和自律管理的非营利性社会团体法人&#xff0c;于2012年&#xff0c;经上海市经济和信息化委同意&#xff0c;在上海市社团局登记成立。 本…

【精选】Spring整合MyBatis,Junit 及Spring 事务Spring AOP面向切面详解

Spring整合MyBatis 搭建环境 我们知道使用MyBatis时需要写大量创建SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession等对象的代码&#xff0c;而Spring的作用是帮助我们创建和管理对象&#xff0c;所以我们可以使用Spring整合MyBatis&#xff0c;简化MyBatis开发。 …

SDK emulator directory is missing

要进行uniapp真机测试&#xff0c;不得不安装配置一下安卓开发环境 &#xff0c;搞一个模拟器。。。然后又是各种坑。。对比来对比去还是IOS的环境使用着舒服&#xff0c;XCODE下载好&#xff0c;一切重点就是在编码了。。 安卓这个脑残货呀&#xff0c;哎&#xff0c;各种安装…