了解内存函数

 ✨✨欢迎👍👍点赞☕️☕️收藏✍✍评论

个人主页:秋邱'博客

所属栏目:C语言

前言 

 内存函数不止malloc、calloc、realloc、free还有memcpy、memmove、memset、memcmp前四个的头文件是<stdlib.h>,后四个的头文件是<string.h>


1.0 memcpy()

函数声明:

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

destination:指向要复制内容的目标数组的指针,类型转换为void*类型的指针。

source:指向被复制的目标数组的指针,类型转换为const void*类型的指针。(const指针内容不能被修改)

num:字节个数。

返回值:返回一个类型的指针。

注意: 

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

1.1 函数使用

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

打印结果:

1.2 模拟实现

前面对memcpy进行了使用,发现memcpy就是将原内存拷贝到目标内存去的一个函数。

这里用void*来接收指针的地址,因为并不清楚传入函数的是声明类型,所以用void*来接收(void*可以接收任意类型

#include<stdio.h>
void* my_memcopy(void* dest,const void* src, size_t num)
//const这里是拷贝,只需要原地址空间的数据,并不需要修改
{void* ret = dest;while (num--){*(char*)src = *(char*)dest;//将原地址的数据放入目的地址src = (char*)src + 1;//对src和dest为(char*)+1跳过一个字节dest = (char*)dest + 1;}return ret;
}
int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] = { 0 };int num = sizeof(arr1) / sizeof(arr1[0]);my_memcopy(arr1, arr2, num * sizeof(int));for (int i = 0; i < num; i++){printf("%d ", arr2[i]);}return 0;
}

分析:

dest和src均为void*类型,在解引用需要将它们转化为(char*),因为在函数拷贝过程中,并不清楚传入的是int*还是char*等类型,这就需要char*一个一个字节的搬运。

强制类型转换只是临时的,下一次的使用还是原来的类型,也就是dest和src下一次使用还是void*的类型。src = (char*)src + 1将src强换为(char*)赋给src。

开辟一个void*的函数,来存dest的初始地址,最后返回。

对于重叠的内存,交给memmove来处理。


2.0 memmove()

memmove的destination和source相同的

函数声明:

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

destination:指向要复制内容的目标数组的指针,类型转换为void*类型的指针。

source:指向被复制的目标数组的指针,类型转换为const void*类型的指针。(const指针内容不能被修改)

num:字节个数。

返回值:返回一个类型的指针。

2.1 函数使用

int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//代码1memmove(arr+2, arr, sizeof(int)*5);//代码2memmove(arr, arr+2, sizeof(int)*5);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

打印结果:

 代码1

代码2

可以看到,代码1和代码2的打印结果不同,这跟dest在前还是在后有关系,到模拟实现的时候就要分情况来讨论。 

2.2 模拟实现

2.2.1 分析

 2.2.1.1 dest在前,src在后,且有重叠(dest < src)

前向后遍历:3 4 5 6 7 6 7 8 9 10 √

后向前遍历:7 6 7 6 7 6 7 8 9 10 ×

很明显,从前向后遍历才是正确的。

2.2.1.2 src在前,dest在后,且有重叠(dest > src)

前向后遍历:1 2 1 2 1 2 1 8 9 10  ×

后向前遍历:1 2 1 2 3 4 5 8 9 10  √

2.2.1.3 无重叠

前向后遍历=后向前遍历:1 2 3 4 5 1 2 3 4 5

前向后遍历=后向前遍历:5 6 7 8 9 10 5 6 7 8 9 10

使用第三种情况已经被第一二种情况包括了,就不需要拿出来分析了。 只需要讨论前两种就行了。

void* my_memmove(void* dest, const void* src, size_t num)
{void* ret = dest;if (dest < src)//dest在前,src在后{while(num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else{//src在前,dest在后dest = (char*)dest + num-1;src = (char*)src + num-1;while (num--){*(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_memmove(arr+2, arr, sizeof(int)*5);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

dest在前,src在后,且有重叠(dest < src)这个情况跟memcpy的写法一样,只需用if判断dest是否小于src即可。else里只需要将,src里的数据一个字节一个字节的放进dest就可以了。


3.0 memset()

函数声明:

void * memset ( void * ptr, int value, size_t num )

ptr:指向需要被放置的指针。

value:该值作为int类型传递,但函数使用该值的unsigned char转换来填充内存块。

num:字节个数。

返回值:返回一个类型的指针。

3.1 函数使用

int main()
{char ptr[] = "hello world";memset(ptr, 'x', 6);printf("%s", ptr);return 0;
}

打印结果:

 

3.2 模拟实现

void* my_memset(void* ptr, int value, size_t num)
{void* ret = ptr;//while(num--)//{//	*(char*)ptr = (char)value;//	ptr = (char*)ptr + 1;//}for (int i = 0; i < num; i++){*(char*)ptr = (char)value;ptr = (char*)ptr + 1;}return ret;
}
int main()
{char ptr[] = "hello world";my_memset(ptr, 'x', 6);printf("%s", ptr);return 0;
}

分析: 这个函数的实现比较简单,给定一个指针ptr开始,逐个字节地将值(char*)value设置到后续的内存位置,循环执行num次。


4.0 memcmp()

函数声明:

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

ptr1:指向内存块的指针。

ptr2:指向内存块的指针。

num:字节个数。

 返回值:

返回值意思(如果作为unsigned char值计算)
<0ptr1的值小于ptr2的值
=0ptr1的值等于ptr2的值
>0ptr1的值大于ptr2的值

4.1 模拟实现

int memcmp(const void* ptr1, const void* ptr2, size_t num)
{if (*(char*)ptr1 > *(char*)ptr2)return 1;else if (*(char*)ptr1 < *(char*)ptr2)return -1;else{ptr1 = *(char*)ptr1 + 1;ptr2 = *(char*)ptr2 + 1;}return 0;
}
int main()
{char arr1[] = "Hello Qiu";char arr2[] = "Hello qiu";int ret = memcmp(arr1, arr2, sizeof(arr1));if (ret > 0)printf("'%s' is greater than '%s'.\n", arr1, arr2);else if (ret < 0)printf("'%s' is less than '%s'.\n", arr1, arr2);elseprintf("'%s' is the same as '%s'.\n", arr1, arr2);return 0;
}

将传入的指向用void*接收,ptr1和ptr2一个字节一个字节的进行比较,若ptr1大,则返回大于0的值;ptr1相等ptr2,且*ptr1+1、*ptr2+1直到全部比完相同,返回0;ptr2大,返回小于0的值。


感谢各位大佬莅临,如有错误欢迎指出,共同学习进步。 

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

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

相关文章

Ansible----playbook模块之templates模块、tags模块、roles模块

目录 引言 一、templates模块 &#xff08;一&#xff09;关键信息 &#xff08;二&#xff09;实际操作 1.定义主机组 2.设置免密登录 3.分别建立访问目录 4.定义模板文件 5.创建playbook文件 6.执行剧本 7.验证结果 二、tags模块 &#xff08;一&#xff09;创建…

《QT实用小工具·六十一》带动画的三角形指示箭头

1、概述 源码放在文章末尾 该项目实现了一个带动画效果的三角形指示箭头&#xff0c;项目demo演示如下所示&#xff1a; 用法 interestingindicate.h interestingindicate.cpp 放到工程中&#xff0c;直接使用即可。 注意&#xff1a;建议绝对布局&#xff0c;手动指定 wid…

华为车BU迈入新阶段,新任CEO对智能车的3个预判

作者 |张马也 编辑 |德新 4月24日&#xff0c;北京车展前夕&#xff0c;华为召开了新一年的智能汽车解决方案新品发布会。 这次发布会&#xff0c;也是华为智能汽车解决方案BU&#xff08;简称「车BU」&#xff09;CEO 靳玉志的公开首秀。 一开场&#xff0c;靳玉志即抛出了…

BACnet转MQTT网关智联楼宇json格式自定义

智能建筑的BACnet协议作为楼宇自动化领域的通用语言&#xff0c;正逐步迈向更广阔的物联网世界。随着云计算和大数据技术的飞速发展&#xff0c;如何将BACnet设备无缝融入云端生态系统&#xff0c;成为众多楼宇管理者关注的焦点。本文将以一个实际案例&#xff0c;揭示BACnet网…

Clion STM32CubeMX 项目

系列文章目录 前言 最后修改 2024 年 4 月 16 日 操作系统&#xff1a;Windows / Linux / macOS 所需工具 STM32CubeMX、GNU ARM 工具链 项目格式&#xff1a; CMake 兼容配置&#xff1a; OpenOCD 运行与调试/嵌入式 GDB 服务器 对于以 STM32 板卡为目标的嵌入式项目&#xf…

分布式与一致性协议之ZAB协议(七)

ZAB协议 ZAB协议:如何处理读写请求 你应该有这样的体会&#xff0c;如果你想了解一个网络服务&#xff0c;执行的第一个功能肯定是写操作&#xff0c;然后才会执行读操作。比如&#xff0c;你要了解ZooKeeper&#xff0c;那么肯定会在zkClient.sh命令行中执行写操作(比如crea…

如何购买阿里云99计划的ECS云服务器?99元购买阿里云2核2G3M服务器教程

阿里云助力中小企业和开发者无忧上云的“99计划”中有两款性价比超高的ECS云服务器&#xff0c;2026年3月31日活动结束前新购和续费价格一样。 其中个人和企业新老用户同享的2核2G3M服务器仅需99元/年&#xff08;续费同价&#xff09;&#xff0c;企业新老用户同学的2核4G5M仅…

Python 框架安全:Django SQL注入漏洞测试.(CVE-2021-35042)

什么是 Django 框架 Django 是一个用 Python 编写的 Web 应用程序框架。它提供了许多工具和库&#xff0c;使得开发 Web 应用程序变得更加容易和高效。Django 遵循了“MTV”&#xff08;模型-模板-视图&#xff09;的设计模式&#xff0c;将应用程序的不同组件分离开来&#x…

《从零开始,搭建一个简单的UVM验证平台》实操

最近的工作中需要用UVM平台去仿真软件同事写的C程序&#xff0c;虽然只要用EDA同事已经搭好的UVM平台稍微改改就行&#xff0c;但对于我这种从未接触过UVM甚至都没用过System Verilog的纯FPGA工程师来说还是很有难度的&#xff0c;因为我对这方面一点概念都没有。 基于此&…

[Kubernetes] 安装KubeSphere

选择4核8G&#xff08;master&#xff09;、8核16G&#xff08;node1&#xff09;、8核16G&#xff08;node2&#xff09; 三台机器&#xff0c;按量付费进行实验&#xff0c;CentOS7.9安装Docker安装Kubernetes安装KubeSphere前置环境: nfs和监控安装KubeSphere masternode1no…

【QT学习】14.线程学习

一。线程了解 线程是计算机科学中的一个重要概念&#xff0c;它是操作系统能够进行运算调度的最小单位。线程是进程中的一个执行流&#xff0c;一个进程可以包含多个线程。与进程相比&#xff0c;线程更轻量级&#xff0c;可以更高效地利用计算机资源。 线程有以下几个特点&…

OpenCV|简单绘制一个矩形

OpenCV中的rectangle() 为绘制矩形命令&#xff0c;形式如下&#xff1a; # (img: cv2.typing.MatLike, pt1: cv2.typing.Point, pt2: cv2.typing.Point, color: cv2.typing.Scalar, thickness: int ..., lineType: int ..., shift: int ...)cv2.rectangle(img, pt1, pt2, …

Dynamic Extraction of Subdialogues for Dialogue Emotion Recognition

对话情感识别的子对话动态提取 摘要1. 介绍2 相关工作2.1 对话上下文建模2.2 常识知识 3 方法3.1 问题定义3.2 模型概述3.3 特征提取模块3.4 依赖性建模3.5 交互式子对话提取模块3.6 重要性增强的多头自注意力模块3.7 子对话框主题提取模块3.8. 分类模块 四、实验4.1 数据集4.1…

含义:理财风险等级R1、R2、R3、R4、R5

理财风险等级R1、R2、R3代表什么&#xff0c;为什么R1不保本&#xff0c;R2可能亏损 不尔聊投资https://author.baidu.com/home?frombjh_article&app_id1704141696580953 我们购买理财产品的时候&#xff0c;首先都会看到相关产品的风险等级。风险等级约定俗成有5级&…

Java进阶07集合(续)

Java进阶07 集合&#xff08;续&#xff09; 一、数据结构&#xff08;树&#xff09; 1、关于树 1.1 相关概念 节点&#xff1a;树中每个单独的分支 节点的度&#xff1a;每个节点的子节点数量 树高&#xff1a;树的总层数 根节点&#xff1a;最顶层节点 左子节点&…

Python专题:三、数字和运算(2)

目录 一、数学运算 二、赋值运算 一、数学运算 1、运算符号 加法 减法- 乘法* 除法/ 计算机中浮点数表示有精度限制&#xff0c;Python有限&#xff0c;所以近似取数 2、除法取整// Python2中 整数/整数 值为整数 Python3中 整数/整数 整数or浮点数 //计算除法对结果取…

2024年最适合做的母婴赛道,选品思路揭秘,教你如何选品!

大家好&#xff0c;我是电商花花。 在我印象中&#xff0c;每年都有人唱衰抖音小店不好做了&#xff0c;太卷了&#xff0c;普通人没有机会了&#xff0c;但是现在直播电商时代&#xff0c;很多信息都会片面的&#xff0c;做不好并不是因为不好做&#xff0c;而是因为你做不好…

60*13薪,外包到新疆...去吗?

大家好&#xff0c;我是白露呀。 今天我在牛客上看到一篇帖子&#xff0c;一位网友说自己收到一个 offer &#xff0c;薪资很高&#xff1a;60k*13&#xff0c;大约一年有近80万。 但是有个要求是外包到新疆的乌鲁木齐&#xff0c;他拿不定主意&#xff0c;就在牛客上发了这个…

Crocoddyl 使用教程(二)

系列文章目录 前言 小车摆杆是另一个经典的控制实例。在这个系统中&#xff0c;一根欠驱动的杆子被固定在一辆一维驱动的小车顶部。游戏的目的是将杆子升到站立位置。 模型如下&#xff1a; https://en.wikipedia.org/wiki/Inverted_pendulum 我们用 表示小车质量、 表示摆杆质…

Agent Hospital: 一种可进化医疗代理人的医院模拟器

论文来源: https://arxiv.org/pdf/2405.02957 1 引言 大型语言模型(LLM)代理在各种任务中表现出了有前景的性能,包括代码生成、信息博弈和问答等。受 LLM 代理能力的启发,一些研究采用它们来模拟人类互动和行为,而不是处理单一任务,例如社交媒体上的信息传播和"Stanford…