C语言内存函数(1)【memcpy函数的使用与模拟实现】【memmove函数的使用和模拟实现】

2024-03-24 09:44

本文主要是介绍C语言内存函数(1)【memcpy函数的使用与模拟实现】【memmove函数的使用和模拟实现】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

关于内存函数有四个函数需要我们学习。分别是memcpy,memmove,memset和memcmp。都在头文件string.h里面。

一.memcpy函数的使用

一提到这个函数,我们可能会联想到strcpy函数,但strcpy函数是针对字符串的拷贝。但是我们在写代码的时候不可能只拷贝字符串。

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

在这里我想把arr1前五个元素拷贝到arr2里面,要怎么样实现呢?这里我们就可以使用memcpy。大家注意,memcpy是针对内存块进行拷贝的。它是有三个参数的。

它的前两个参数都是void*类型的指针。

(1)函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置(2)这个函数在遇到'\0'后不会停下来(3)如果source和destination有任何的重叠,复制的结果都是未定义的。下面我来用代码演示一遍。

#include<stdio.h>
#include<string.h>
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,0 };int arr2[20] = { 0 };memcpy(arr2, arr1, 20);//注意这里的20单位是字节for (int i = 0; i < 5; i++){printf("%d ", arr2[i]);}return 0;
}

最终也是成功可以打印出来1,2,3,4,5。到这里相信也可以看出来这个函数具体的作用了。

二.memcpy函数的模拟实现

这个函数的模拟实现不是太容易,我尽量写的详细一点。

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* sec, size_t num)
{void* ret = dest;//先把dest的起始地址给存起来assert(dest && sec);//assert断言,判断dest和sec是不是空指针while (num--)//num总共有20个字节,这里循环20次{*(char*)dest = *(char*)sec;//大家注意void*类型的指针不能直接解引用,这里强制转换成char*类型的指针//强制类型转换后,再次解引用,也就是使用char*类型解引用访问一个字节,所以这里赋值的时候也是一次赋值一个字节//至于为什么强制转换成char*类型,是为了避免num为单数,比如3,5,7。((char*)sec)++;//注意也不要写成(char*)sec++,因为这里强转只是临时的,当我们++的时候就不是强转之后的结果。((char*)dest)++;//这里也是一次加一个字节往后赋值}return ret;
}
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,0 };int arr2[20] = { 0 };my_memcpy(arr2, arr1, 20);//注意这里的20单位是字节for (int i = 0; i < 5; i++){printf("%d ", arr2[i]);}return 0;
}

大家注意,假如我的内存有重叠的话,这个我写的memcpy函数的模拟实现是实现不了的。简单的说,我想把arr1的前五个元素拷贝到3,4,5,6,7的位置上,将arr1数组的元素变成1,2,1,2,3,4,5,8,9,0.这里我截屏看一下。

大家可以看到如果我用我写的my_memcpy函数是不能实现的。因为当我们把数组的第三个元素给覆盖之后,这里就变成了1,第四个元素就变成了2。当我们再次把第三个元素赋值给第五个元素的时候,其实是把已经变成1的第三个元素赋值给第五个元素。依次类推,赋值的结果就只能是一开始就复制成功的1和2。

但是如果我不使用自己写的,我们使用库函数的话,大家再来看。

这里竟然也成功的赋值了。还记得上面我说的第三个定义吗,即使这个库函数可以实现这样内存重叠的赋值,但是我们不给予这个函数可以达到这个作用的希望。我们认为,memcpy这个函数只要可以完成内存没有重叠时赋值的作用就可以了。对于内存重叠的部分我们用另一个库函数来进行。上面我写的my_memcpy就已经可以发挥出memcpy的作用了。接下来我就来介绍memmove。

三.memmove函数的使用

这个函数的参数和memcpy的参数都是一样的。

memmove与memcpy差别就是memmove处理的源内存块和目标内存块是可以重叠的。而且只要源内存块和目标内存块只要出现重叠就得使用memmove函数来处理。

还是用上面的代码来让大家看一下。

这里的使用我就不过多介绍了,因为这个函数使用起来是比较简单的,难的是模拟实现。

四.memmove的函数模拟实现

关于这个函数的实现,我们主要考虑的就是要避免值被覆盖。这里有几种情况大家看一下。

还有从前往后赋值的情况。假如我要把3,4,5,6,7,赋值给1,2,3,4,5。这时就不能再去使用这种从前往后的方式了。

也就是说当dest在src左边的时候咱们就从前往后,在右边的时候咱们就从后向前。这里我画一个区间来让大家更好理解。

这个都可以的意思就是在这里的位置已经不重叠了,不论从哪里开始都可以。现在我来用代码来实现一下这个代码。

#include<stdio.h>
#include <assert.h>
void* my_memmove(char* dest, const char* src, size_t num)
{assert(dest && src);//assert判断空指针的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);}}
}
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,0 };my_memmove(arr+2, arr, 20);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

这两个函数的模拟实现跟之前的函数相比难度有些提升了。不过不影响我们去学会。

感谢大家的观看,如有错误请多多指正。

这篇关于C语言内存函数(1)【memcpy函数的使用与模拟实现】【memmove函数的使用和模拟实现】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/841225

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi