实现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 * ...
随机推荐
- 阿里云CentOS 7.3安装Redis详细步骤
############ 准备 ############### 从Redis官网下载Linux redis3.2.6版本,我下载的redis-3.2.6.tar.gz(目前最新稳定版),下载到/u ...
- 大型网站技术架构,4网站的高性能架构之Web前端性能优化
一般说来Web前端指网站业务逻辑之前的部分,包括浏览器加载.网站视图模型.图片服务.CDN服务等,主要优化手段有优化浏览器访问.使用反向代理.CDN等. 4.2.1 浏览器访问优化 1.减少http请 ...
- Jeecg心得篇--这个世界不缺程序员,而是缺少匠人和架构师
真正的快乐,是用自己喜欢的方式过完这一生.来人间一趟,不能只为了活着. 这个世界不缺程序员,而是缺少匠人精神的架构师与产品经理. 因为他们通过自己的行为与理念默默地改变着世界,一个更好的世界. 这是我 ...
- 【C++进阶:STL常见性质】
STL中的常用容器包括:顺序性容器(vector.deque.list).关联容器(map.set).容器适配器(queue.stac) 转载自:https://blog.csdn.net/u0134 ...
- 术语-EDI:EDI
ylbtech-术语-EDI:EDI 电子数据交换(Electronic data interchange,缩写EDI)是指按照同一规定的一套通用标准格式,将标准的经济信息,通过通信网络传输,在贸易伙 ...
- CSS - 层叠上下文(The stacking context)
对 MDN 的上的例子的拓展 Root - DIV #1(z-index: 5) - DIV #2(z-index: 2) - DIV #3(z-index: 4) - DIV #4(z-index: ...
- 项目开源-基于ASP.NET Core和EF Core的快速开发框架
前言:作为一名95后的程序猿,已经写了一年多的代码了,为了提升自己的技术水平,所以决定尝试编写一个快速开发框架开源出来,一来提升自己的技术水平,二来助力.NET Core生态发展 写这个框架主要是为了 ...
- Java 八大基本数据类型
相关信息获取: (1)最小值:包装类.MIN_VALUE,如 Integer.MIN_VALUE (2)最大值:包装类.MAX_VALUE,如 Integer.MAX_VALUE (3)二进制位数:包 ...
- mysql5.7插入数据报错 Incorrect integer value
mysql5.7插入字符串为空的时候取出来的值设置为null
- Git016--Work
GIT常用命令 git常用命令: //初始化git目录: $ git init //把当前目录变成git可以管理的仓库 //添加文件到暂存区 $ git add file //把文件添加到仓库 $ g ...