关于我、重生到500年前凭借C语言改变世界科技vlog.18——内存函数

文章目录

  • 1. memcpy函数
  • 2. memmove函数
  • 3. memset函数
  • 4. memcmp函数
  • 希望读者们多多三连支持
  • 小编会继续更新
  • 你们的鼓励就是我前进的动力!

内存函数是用于 操作内存块的一组函数,它们可以对内存进行复制、移动、设置和比较等操作。这些函数主要在 <string.h> 头文件中声明,其操作对象通常是字节序列,不管这些字节代表的是字符、整数还是其他数据类型

1. memcpy函数

memcpy 主要用于将一段内存中的数据完整地复制到另一段内存中,在很多场景下都非常有用,例如在处理数组、结构体等数据结构时,从源内存地址 src 复制 n 个字节的数据到目标内存地址 destination

在这里插入图片描述

传送门:memcpy-C++参考

参数:destination-目标内存地址,它是一个 void* 类型的指针,source-源内存地址,同样是 void* 类型(不可修改),num-要复制的字节数

返回值:返回指向目标内存地址 destination 的指针

值得注意的是:函数 memcpy 从 source 的位置开始向后复制 num 个字节的数据 destination 指向的内存位置,这个函数在遇到 ‘\0’ 的时候并不会停下来,如果 source 和destination 有任何的重叠,复制的结果都是未定义的

eg

#include <stdio.h>
#include <string.h>int main()
{char src[] = "Hello, World!";char dest[20];memcpy(dest, src, strlen(src)+1);printf("%s\n", dest);return 0;
}

memcpy 函数将 src 数组中的字符串(包括字符串结束符 \0 )复制到 dest 数组中 strlen(src)+1 是为了把 \0 也复制过去

memcpy 的模拟实现

void* memcpy(void* dst, const void* src, size_t count)
{void* ret = dst;assert(dst);assert(src);/** copy from lower addresses to higher addresses*/while (count--) {*(char*)dst = *(char*)src;dst = (char*)dst + 1;src = (char*)src + 1;}return(ret);
}

将dst和src先强制转换为char*类型,实现了以字节为单位的访问和赋值操作,因为 char类型在内存中占用一个字节,所以这样可以逐个字节地复制数据,而不管原始数据的类型是什么,分别将目标地址 dst 和源地址 src 向后移动一个字节的位置,以便在下一次循环中复制下一个字节的数据

2. memmove函数

memmove 和 memcpy 类似,也是从源内存地址 source 复制 num 个字节的数据到目标内存地址destination ,但是 memmove 函数能够处理源内存区域和目标内存区域重叠的情况

在这里插入图片描述

传送门:memmove-C++参考

参数:destination-目标内存地址,它是一个 void* 类型的指针,source-源内存地址,同样是 void* 类型(不可修改),num-要复制的字节数

返回值:返回指向目标内存地址 destination 的指针

值得注意的是:和 memcpy 的差别就是 memmove 函数处理的源内存块和目标内存块是可以重叠的,如果源空间和目标空间出现重叠,就得使用 memmove 函数处理

eg

#include <stdio.h>
#include <string.h>int main()
{char str[] = "abcdef";// 将字符串中的后3个字符向前移动2个位置memmove(str + 2, str + 3, 3);printf("%s\n", str);return 0;
}

str + 3 是源地址,str + 2 是目标地址,存在重叠部分,memmove 函数可以正确地完成复制操作,而 memcpy 函数不能完成有重叠的操作

mememove 的模拟实现

void* memmove(void* dst, const void* src, size_t count)
{void* ret = dst;if (dst <= src || (char*)dst >= ((char*)src + count)) {/** Non-Overlapping Buffers* copy from lower addresses to higher addresses*/while (count--) {*(char*)dst = *(char*)src;dst = (char*)dst + 1;src = (char*)src + 1;}}else {/** Overlapping Buffers* copy from higher addresses to lower addresses*/dst = (char*)dst + count - 1;src = (char*)src + count - 1;while (count--) {*(char*)dst = *(char*)src;dst = (char*)dst - 1;src = (char*)src - 1;}}return(ret);
}

首先判断源内存区域和目标内存区域是否有重叠情况,然后就是分为非重叠和重叠的情况和 memcpy 模拟实现类似的操作

3. memset函数

memset 能将指定内存区域 ptr 的前 num 个字节设置为指定的值 value

在这里插入图片描述

传送门:memset-C++参考

参数:ptr-要设置的内存区域的起始地址,是 void* 类型,value-要设置的值,这个值会被转换为 unsigned char 类型后进行设置,num-要设置的字节数

返回值:返回指向设置后的内存区域 ptr 的指针

值得注意的是:设置完内容后,记得在后面加上 \0

eg

#include <stdio.h>
#include <string.h>int main()
{char buffer[10];memset(buffer, 'A', 5);buffer[5]='\0';printf("%s\n", buffer);return 0;
}

memset 将 buffer 数组的前 5 个字节设置为字符A,然后手动添加字符串结束符 \0 ,以便能够正确地使用 printf 输出字符串

4. memcmp函数

memcmp 用于比较两个内存区域 ptr1 和 ptr2 的前 num 个字节
在这里插入图片描述

传送门:memcmp-C++参考

参数:ptr1、ptr2-要比较的两个内存区域的起始地址,都是 const void* 类型,num-要比较的字节数

返回值
• 如果 ptr1 所指向的内存区域的前 num 个字节大于 ptr2 所指向的内存区域的前 num 个字节,返回一个大于 0 的值
• 如果 ptr1 所指向的内存区域的前 num 个字节小于 ptr2 所指向的内存区域的前 num 个字节,返回一个小于 0 的值
• 如果 ptr1 所指向的内存区域的前 num 个字节等于 ptr2 所指向的内存区域的前 num 个字节,返回 0

值得注意的是:比较从 ptr1 和 ptr2 指针指向的位置开始,向后的 num 个字节,遇到第一个不一样的比较就行了

eg

#include <stdio.h>
#include <string.h>int main()
{char str1[] = "abc";char str2[] = "abd";int result = memcmp(str1, str2, 3);printf("%d\n", result);return 0;
}

memcmp 比较 str1 和 str2 的前 3 个字节,因为 c 的 ASCII 码小于 d 的 ASCII 码,所以返回一个小于 0 的值

以上就是主要使用的内存函数,过几天就参加全国计挑了,希望可以拿个奖,没拿到就当练手了吧,毕竟竞赛经验更重要🤩

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

请添加图片描述

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

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

相关文章

下划线命名json数组转java对象

/*** 将驼峰式命名的字符串转换为下划线方式* @param camelCase* @return*/ private static String toUnderlineCase(String camelCase) {return StrUtil.toUnderlineCase(camelCase); }/*** 下划线-赋值给-驼峰* @param source 源数据* @param target 目标数据*/ public stati…

【计算机网络】Socket编程接口

一、sockaddr结构体 二、Socket常见接口 1. socket() 2. bind() 3. recvfrom() 4. sendto() 5. listen() 6. accept() 三、基本转换函数 1. 与port有关的转换 2.与ip有关的转换 IP地址的表示有两种&#xff1a;点分十进制表示和整数表示 "192.168.1.100" …

ReactOS 4.2 OBJECT_TYPE_INITIALIZERj结构体的实现

Windows内核为新对象类型的定义提供了一个全局的OBJECT_TYPE_INITIALIZER 数据结构,作为需要填写和递交的“申请单”: OBJECT_TYPE_INITIALIZER // // Object Type Initialize for ObCreateObjectType // typedef struct _OBJECT_TYPE_INITIALIZER {USHORT Length;BOOLEAN Us…

SpringCloud篇(注册中心 - Nacos)

目录 一、Nacos安装指南 1. Windows安装 1.1. 下载安装包 1.2. 解压 1.3. 端口配置 1.4. 启动 1.5. 访问 2. Linux安装 2.1. 安装JDK 2.2. 上传安装包 2.3. 解压 2.4. 端口配置 2.5. 启动 3. Nacos的依赖 二、Nacos注册中心的入门使用 1. 认识和安装Nacos 2. 服…

链游系统定制化开发:引领游戏产业的新时代

在数字革命的浪潮中&#xff0c;链游&#xff08;区块链游戏&#xff09;作为一种新兴游戏形式&#xff0c;正重新定义游戏产业的发展方向。链游将区块链技术与传统游戏结合&#xff0c;使游戏体验更加公平透明&#xff0c;并赋予玩家真正的资产所有权。这一领域不仅为玩家带来…

TortoiseSVN提示服务器凭证检核错误:站点名称不符

电脑重装了系统&#xff0c;下载了新版本SVN软件&#xff0c;一切准备就绪&#xff0c;准备大干一场。 打开SVN&#xff0c;一遍一遍的提示【TortoiseSVN提示服务器凭证检核错误:站点名称不符】&#xff0c;一次次的让我接受&#xff0c;终于忍受不了了。 TortoiseSVN提示服务…

《传统视觉算法在视觉算法中的地位及应用场景

一、引言 在计算机视觉领域的发展历程中&#xff0c;传统视觉算法扮演了至关重要的角色。尽管近年来深度学习算法在视觉任务中取得了巨大的成功&#xff0c;但传统视觉算法依然具有不可替代的地位。传统视觉算法通常基于数学模型和手工设计的特征&#xff0c;具有计算效率高、…

docker构建jdk11

# 建立一个新的镜像文件&#xff0c;配置模板&#xff1a;新建立的镜像是以centos为基础模板 # 因为jdk必须运行在操作系统之上 FROM centos:7.9.2009# 作者名 MAINTAINER yuanhang# 创建一个新目录来存储jdk文件 RUN mkdir /usr/local/java#将jdk压缩文件复制到镜像中&#…

第四十二章 Vue中使用mutations修改Vuex仓库数据

目录 一、mutations修改仓库数据 1.1. 概述 1.2. mutations修改数据基本步骤 1.3. 完整代码 1.3.1. main.js 1.3.2. App.vue 1.3.3. index.js 1.3.4. Son1.vue 1.3.5. Son2.vue 二、mutations传参语法 2.1. mutations传参基本步骤 2.2. 完整代码 2.2.1. index.js …

六通道CAN集线器

六通道CAN集线器 --SG-CanHub-600 功能概述 SG_CanHub_600是一款具有六路通道的工业级智能 CAN数字隔离中继集线器。 SG_CanHub_600能够实现信号再生、延长通信距离、提高总线负载能力、匹配不同速 率 CAN网络&#xff0c;同时强大的 ID过滤功能可以极大降低 CAN总线负荷&a…

学校服务器连接pycharm配置2

上一个可能还是有点问题&#xff0c;因为实际在跑的时候读取的其实是本地的anaconda&#xff0c;这个重新整了一下流程 首先在学校服务器先激活自己创建的虚拟环境&#xff0c;这里就不截图了 然后在pycharm里面打开设置 选择这个python解释器 这里有添加解释器 选择SSH …

基于node一键发布到服务器的js脚本

基于node一键将打包后的前端文件发布到服务器指定目录的js脚本 需要使用node的2个包 npm install ssh2 scp2基于node进行ssh连接的控件 下面直接贴代码&#xff0c;已经在代码中加了注释 const { exec } require(child_process); const { Client } require(ssh2); const …

LeetCode面试经典150题|228.汇总区间

给定一个 无重复元素 的 有序 整数数组 nums 。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说&#xff0c;nums 的每个元素都恰好被某个区间范围所覆盖&#xff0c;并且不存在属于某个范围但不属于 nums 的数字 x 。 列表中的每个区间范围 [a,b] 应该按…

excel-VLOOKUP函数使用/XVLOOKUP使用

多个窗口同时编辑表格&#xff0c;方便对照操作 使用开始-视图-新建窗口 将战区信息表的三列数据匹配到成交数据表上 可以使用VLOOKUP函数 有4个参数&#xff08;必须要查找的值&#xff0c; 要查找的区域&#xff0c;要返回区域的第几列数据&#xff0c;一个可选参数查找匹…

boost::intrusive_ptr为什么叫做倾入指针

boost::intrusive_ptr的命名来源于其工作原理和设计目的。这个智能指针被称为“倾入指针”&#xff08;intrusive&#xff09;是因为它依赖于对象本身提供的功能来管理引用计数&#xff0c;而不是像std::shared_ptr和std::weak_ptr那样在指针内部自动管理引用计数。 具体来说&…

kafka和Flume的整合

目录 一、Kafka作为Source 【数据进入到kafka中&#xff0c;抽取出来】 1、在我的flume的conf文件夹下&#xff0c;有个myconf文件夹&#xff1a; 2、 创建一个flume脚本文件&#xff1a; kafka-memory-logger.conf 3、测试 二、kafka作为Sink 【数据从别的地方抽取到kafka里…

PCL 点云分割 欧式聚类算法分割

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1欧式聚类分割 2.1.2分割后的可视化 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接: PCL点云算法与项目实战案例汇总(长期更新) 一、概述 本文介…

【运维】如何在不同操作系统上获取计算机硬件信息

目录 引言一、Windows 操作系统1.1 获取 CPU 信息1.2 获取内存信息1.3 获取硬盘信息1.4 获取显卡信息1.5 获取显存信息 二、macOS 操作系统2.1 获取 CPU 信息2.2 获取内存信息2.3 获取硬盘信息2.4 获取显卡信息2.5 获取显存信息 三、Linux 操作系统3.1 获取 CPU 信息3.2 获取内…

Ascend Extension for PyTorch的源码解析

1 源码下载 Ascend对pytorch代码的适配&#xff0c;可从以下链接中获取。 Ascend/pytorch 执行如下命令即可。 git clone https://gitee.com/ascend/pytorch.git2 目录结构解析 源码下载后&#xff0c;如果需要编译torch-npu&#xff0c;最好保持pytorch的源码版本匹配&…

鸿蒙next版开发:ArkTS组件快捷键事件详解

在HarmonyOS 5.0中&#xff0c;ArkTS提供了一种机制&#xff0c;允许开发者为应用中的组件绑定快捷键事件&#xff0c;这极大地增强了应用的交互性和用户体验。本文将详细解读如何在ArkTS中使用组件快捷键事件&#xff0c;并提供示例代码进行说明。 组件快捷键事件基础 组件快…