实现memcpy()函数及过程总结
1.为什么会写memcpy
在之前的应聘笔试上遇到一道笔试题,题目要求实现一个my_memcpy函数。函数原型:void * my_memcpy(void *dst, const void *src, int n);
之前使用的内存拷贝函数是标准库memcpy函数,拿来就用,真没有对这个函数做过多了解。在网上查了一下,有好多关于memcpy函数优化的文章。
在实现过程中了解的越多,往往实现起来越麻烦。还是先实现简单的memcpy函数。
2.按字节(Byte)拷贝实现的memcpy
void *my_memcpy_byte(void *dst, const void *src, int n)
{
if (dst == NULL || src == NULL || n <= )
return NULL; char * pdst = (char *)dst;
char * psrc = (char *)src; if (pdst > psrc && pdst < psrc + n)
{
pdst = pdst + n - ;
psrc = psrc + n - ;
while (n--)
*pdst-- = *psrc--;
}
else
{
while (n--)
*pdst++ = *psrc++;
}
return dst;
}
//20200104 看到评论,又看了下之前写的memcpy实现
//按字节拷贝实现的memcpy没有问题
//*pdst-- = *psrc--; 查了下运算符优先级(*,--)优先级相同,从右向左结合,psrc--是先使用,后减减
//等价于*pdst = *psrc;psrc--;pdst--;
这里要考虑写覆盖的情况
3.按4字节拷贝实现的memcpy
void *my_memcpy(void *dst, const void *src, int n)
{
if (dst == NULL || src == NULL || n <= )
return NULL; int * pdst = (int *)dst;
int * psrc = (int *)src;
char *tmp1 = NULL;
char *tmp2 = NULL;
int c1 = n / ;
int c2 = n % ; /*if (pdst > psrc && pdst < psrc + n) 这样判断有问题*/
if (pdst > psrc && pdst < (char *)psrc + n)
{
tmp1 = (char *)pdst + n - ;
tmp2 = (char *)psrc + n - ;
while(c2--)
*tmp1-- = *tmp2--;
/*这样有问题,忘记字节偏移
pdst = (int *)tmp1;
psrc = (int *)tmp2;
*/
tmp1++;tmp2++;
pdst = (int *)tmp1;
psrc = (int *)tmp2;
pdst--;psrc--;
while (c1--)
*pdst-- = *psrc--;
}
else
{
while (c1--)
*pdst++ = *psrc++;
35
36 tmp1 = (char *)pdst;
tmp2 = (char *)psrc;
while (c2--)
*tmp1++ = *tmp2++;
}
return dst;
}
//20200104 查看评论说四字节写覆盖拷贝问题,现在已修改
//备注:void *dst, const void *src这两个参数是需要按4字节对齐的,如果本身不是4字节对齐,按4字节拷贝效率也会变低。
这里还是考虑了写覆盖的代码。对比按字节拷贝,拷贝速度是提高不少。
以上是针对笔试过程中写memcpy。
4.如何优化memcpy
高性能的memcpy与很多因数相关,与平台,处理器,编译器,具体拷贝情形等相关。
VS2017中对C库的memcpy进行优化,glibc对memcpy也有优化
5.是否需要考虑内存对齐拷贝?
内存读写效率影响之一:内存对齐
参考:1.浅谈CPU内存访问要求对齐的原因 2.解析内存对齐
如果src,dst的地址是不对齐的,读写效率变低。
通过代码实现不对齐的拷贝,memcpy的实现会变得复杂,反而影响拷贝效率。
这种不对齐情况我们可以预先避免,因为编译器在给我们分配空间时是按照内存对齐进行分配的。
6.根据拷贝数据大小进行优化
1.多次调用memcpy,而每次拷贝数据大小Kb下的小拷贝
这种情况下尽量减少分支预测,代码精简。
2.拷贝Mb的memcpy实现
这种情况影响拷贝效率主要在寻址上。
7.总结
memcpy需要根据情况优化,如 平台,处理器,拷贝大小。
实现memcpy()函数及过程总结的更多相关文章
- memcpy函数的用法以及实现一个memcpy函数
memcpy的用法 在项目中经常用到memcpy来实现内存的拷贝工作,如下代码片段 memcpy( pData, m_pSaveData_C, iSize * sizeof( unsigned sho ...
- 利用memcpy函数实现float到QByteArray的相互转化
一.为什么要实现float到QByteArry之间的相互转化 在总线通讯过程中(例如串口通讯),总线上传输的是字节数组变量,即ByteArray型的变量,在Qt中即为QbyteArray型变量.总线发 ...
- memmove和memcpy函数的区别及实现
一.memmove()和memcpy()函数和strcpy()函数的区别: (1)使用的类型不同,strcpy()函数只对字符串进行操作:memmove()和memcpy()函数对所有类型都适用,为内 ...
- C语言memcpy()函数和memmove()函数
C语言memcpy()函数和memmove()函数 关于 memcpy() 函数,请先看链接. memcpy() 函数和 memmove() 函数的函数原型如下: void* memcpy(void ...
- memcpy函数用法
memcpy函数用法 .分类: VC++ VC++ mfc matlab 2011-12-01 19:17 14538人阅读 评论(0) 收藏 举报 null 原型:extern void *memc ...
- C语言之memcpy函数
昨天自己动手实现memcpy这个函数,用一个例程试了一下,结果正确,满心欢心,可是有些地方想不明白,于是百度了一下,结果自己写的函数简直无法直视. 觉得还是写个总结,以示教训. 先贴上我自己的函数: ...
- 【转】【C/C++】实现memcpy函数
本文转自:http://my.oschina.net/renhc/blog/36345 面试中如问到memcpy的实现,那就要小心了,这里有陷阱. 先看下标准memcpy()的解释: ? 1 2 vo ...
- memcpy函数
实现1:<高质量c++,c编程指南> void *mymemcpy(void *dst,const void *src,size_t num) { assert((dst!=NULL)&a ...
- memcpy函数的使用方法
c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中. 1.函数原型 void *memcpy(void * ...
随机推荐
- string matching
string matching exkmp #include<bits/stdc++.h> using namespace std; ; int Nex[maxn],extend[maxn ...
- es之关于consistency(数据一致性问题)
Es集群内部是有一个约定是用来约束我们的写操作的,就是“一致性”: 也就是说:新建.索引.删除这些操作都是写操作,他们都有一个大前提: 当前的分片副本处于活跃状态的数量 >= int( (pri ...
- Spring定时器Quartz
<bean id="startQuertz" lazy-init="false" autowire="no" class=" ...
- win10文件夹不自动刷新的解决方案
win10文件夹不自动刷新的解决方案 https://jingyan.baidu.com/article/d7130635d45a5013fcf47544.html
- 项目二、自定义文件上传函数(js函数)
/** * 文件上传工具 v1.0 * @param file 要上传的文件 * @param url 要上传到的路径 * @param div 要显示的区域 */ function uploader ...
- 微信小程序 input 组件
输入框:该组件是原生组件,使用的时候要注意相关的设置 属性: value:类型 字符串 输入框的初始内容 type:类型 字符串 input类型 属性值:text 文本输入键盘 number 数字输入 ...
- IIS知识点总结
一.命令行启动IIS Express 转自:https://www.cnblogs.com/cby-love/p/7102847.html 我们在调试WEB程序的时候可以把本地web程序挂载到本地II ...
- 术语-BPM:BPM
ylbtech-术语-BPM:BPM BPM,即业务流程管理,是一种以规范化的构造端到端的卓越业务流程为中心,以持续的提高组织业务绩效为目的的系统化方法,常见商业管理教育如EMBA.MBA等均将BPM ...
- (二)Maven之坐标和依赖
目录 坐标 依赖 目录 坐标 引言: 坐标是依赖管理的基础,是构建的唯一标识. 组成元素: 使用groupId.artifactId.version.packaging.classifier标签即可定 ...
- 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_06 Set集合_4_Set集合存储元素不重复的原理
set集合元素为什么不能重复 集合重写了toString的方法所以打印是里面的内容 往里面存了三次abc 哈希表,初始容量是16个 set集合存储字符串的时候比较特殊 横着是数组,竖着就是链表结构.跟 ...