内存函数memcpy&memmove分析与实现
2022/2/21 7:30:19
本文主要是介绍内存函数memcpy&memmove分析与实现,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1.几个常见常用内存函数的介绍与使用
在字符串库函数中,strcpy这类函数可以轻松对字符串进行修改,但如果换成int、double这类类型数据时,str家族显得无能为力,由此,mem家族(内存函数)诞生,并可以轻松地解决这类问题
首先我们来看memcpy和memmove 官方给的函数原型与介绍
推荐查阅网站:
en.cppreferrence.com
cplusplus.com
memcpy和memmove的作用是将src指针处的前count个字节内容拷贝到dest处
特注:此处size_t count是指字节数
他们有三个参数 目标指针dest 源地址src 字节数count
此处开发者将两个关键指针和memcpy/memmove的返回类型都设置为void*
原因就是为了适配,因为开发者无法得知使用者在调用函数时适配的类型,于是设置为百变怪-void*
举个例子 尝试使用这两个函数(以memcpy为例,memmove的使用同理)
#include<stdio.h> #include<string.h> int main() { int arr1[10] = {1,2,3,4,5,6,7,8,9}; int arr2[10] = { 0 }; memcpy(arr2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr2[i]); } return 0; }
想把arr1中前20个字节的元素拷贝到arr2中并打印 这便是内存函数memcpy的作用
效果如→:
2.memcpy模拟实现
成品如下:
//模拟实现memcpy void* my_memmcpy(void* dest, const void* src, size_t n) { void* ret = dest; assert(dest&&src); while (n--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } return ret; }
因为我们在执行memcpy功能时,不会对源指针进行修改,所以这里加const修饰;
char* 一个字节为单位,强制类型转换和我们要拷贝的字节数单位一致;
但是强制类型转化都是临时的,我们在对dest,src操作时切忌dest++,src++,我们还要进行强制类型转化,拷贝一个字节dest、src往后走一个字节;
此处用assert保证dest与src指针为非空指针;
3.memcpy与memmove的区别
我们先来看这个代码
int main() { int arr[] = { 1,2,3,4,5,6,7,8,9,10}; my_memcpy(arr + 2, arr, 5 * sizeof(arr[0])); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr[i]); } return 0; }
此时我们使用的是自己设计的my_memcpy函数 我们预期的运行结果是
1 2 1 2 3 4 5 8 9 10
但我们会惊讶地发现运行结果和我们设想的不同
这是为什么呢?
这里出现了内存覆盖的情况 我们原本要拷贝的3 4 5被拷贝过来的1 2 1覆盖 导致后面要拷贝3 4 5时 拷贝了1 2 1;
特注特注特注:如果你和博主一样使用vs编译器的话,memcpy在此处可以解决内存重叠的问题,我们可以用memcpy得到下图的预期效果(在某些编译器下memcpy可能不支持重叠拷贝);
但是,C语言库只要求memcpy处理内存不重叠情况 memmove来处理内存重叠的情况;
此时就要使用memmove函数 memmove在进行拷贝的时候,是允许内存重叠的;
这便是我们想要的拷贝效果
其实在处理这类问题时,无脑用memmove就完事了;
4.memmove模拟实现
成品如下:
//模拟实现memmove void my_memmove(void* dest, const void* src, size_t n) { void* ret = dest; assert(dest && src); if (dest < src) { while (n--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src =(char*)src + 1; } } else { while (n--) { *((char*)dest + n) = *((char*)src + n); } } return ret; }
细节与memcpy实现时同理;
在实现3中的重叠问题时,我们可以倒着拷贝
此时dest>src
但dest<src时,倒着拷贝明显也会出现内存重叠
所以此处我们正着拷贝,一个分类解决问题;
5.总结
memcpy是C语言在发展史中诞生的产物,没办法抹消掉,但他并不是毫无意义;
我们在碰到要使用内存函数拷贝时,使用memmove就可以了;
如有错误,多多斧正;一起成长 一起加油!
这篇关于内存函数memcpy&memmove分析与实现的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享