当前位置: 首页 > news >正文

关于我、重生到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.mrgr.cn/news/72344.html

相关文章:

  • 使用php和Xunsearch提升音乐网站的歌曲搜索效果
  • Dockerfile详解:构建简单高效的容器镜像
  • tcpdump交叉编译
  • Elasticsearch 6.8 分析器
  • C++桥接模式在使用时需要注意什么
  • 爬虫开发工具与环境搭建——使用Postman和浏览器开发者工具
  • Rocky linux8 安装php8.0
  • CesiumJS 案例 P27:创建椭圆、创建带边框的椭圆、创建圆、创建带边框的圆、创建椭圆环、创建圆环
  • WPF 中的视觉层和逻辑层有什么区别?
  • frp搭建内网穿透
  • PMC部门如何精准把控生产计划和生产进度?关键要点全解析
  • 【miniMax开放平台-注册安全分析报告-无验证方式导致安全隐患】
  • day31-二叉树的最大深度
  • Git服务部署教程
  • Linux中扫描网络的“nmap”工具使用方法
  • Conda安装软件错误(Pycharm)
  • 【更新中】《硬件架构的艺术》笔记(二):时钟与复位
  • 使用Flask部署自己的pytorch模型(猫品种分类模型)
  • 举例说明自然语言处理(NLP)技术。
  • 丹摩征文活动|CogVideoX-2b:从0到1,轻松完成安装与部署!
  • 功能性材料立式粉碎机、立式破碎机、立式超细磨、立式磨粉机
  • vxe-table 实现全部单元格都能编辑的方法
  • GPS L1信号捕获跟踪MATLAB仿真(终极版)
  • ubuntu20.04_从零LOD-3DGS的复现
  • 服务器数据恢复——Ext4文件系统使用fsck后mount不上的数据恢复案例
  • netmap.js:基于浏览器的网络发现工具