实现一个高效率的内存拷贝函数memcpy
内存拷贝函数memcpy
memcpy是memory copy的缩写,意为内存复制,在写C语言程序的时候,我们常常会用到它。它的函原型如下:
void *memcpy(void *dest, const void *src, size_t n);
它的功能是从src的开始位置拷贝n个字节的数据到dest。如果dest存在数据,将会被覆盖。memcpy函数的返回值是dest的指针。memcpy函数定义在string.h头文件里。
自己实现的时候,最简单的方法是用指针按照字节顺序复制即可。但是性能太低,因为其一,一次一个字节效率太低,地址总线一般是32位,能搬运4字节,一次一个肯定慢的不行;其二,当内存区域重叠时会出现混乱情况。
一下根据以上两方面考虑提高memcpy函数的性能。首先考虑速度,可以按照CPU位宽搬运数据,效率更高,代码如下:
void * Memcpy1(void *dst,const void *src,size_t num)
{int nchunks = num/sizeof(dst); /*按CPU位宽拷贝*/cout<<"sizeof(dst)是:"<<sizeof(dst)<<endl;int slice = num%sizeof(dst); /*剩余的按字节拷贝*/unsigned long * s = (unsigned long *)src;unsigned long * d = (unsigned long *)dst;while(nchunks--)*d++ = *s++;while (slice--)*((char *)d++) =*((char *)s++);return dst;
}
sizeof(dst)是4,即大部分数据每次按照4字节拷贝,最后不足4字节的再分别拷贝。但是内存区域出现重叠时,这种方法无法规避内存混乱问题。
下面的方法能够规避内存重叠的bug,代码如下:
void *Memcpy2(void *dest, const void *src, size_t count)
{ char *d; const char *s; if (((int)dest > ((int)src+count)) || (dest < src)) { d = (char*)dest; s = (char*)src; while (count--) *d++ = *s++; } else /* overlap */ { d = (char *)((int)dest + count - 1); /* 指针位置从末端开始,注意偏置 */ s = (char *)((int)src + count -1); while (count --) *d-- = *s--; } return dest;
}
如果检测到内存区域有重叠部分,则从末端开始对每个字节进行拷贝。但数据量大时速度慢,将两种方法结合后能够提高拷贝函数性能,代码如下:
void *Memcpy(void *dest, const void *src, size_t count)
{ cout<<"sizeof(dest)是:"<<sizeof(dest)<<endl;int bytelen=count/sizeof(dest); /*按CPU位宽拷贝*/int slice=count%sizeof(dest); /*剩余的按字节拷贝*/unsigned int* d = (unsigned int*)dest; unsigned int* s = (unsigned int*)src; if (((int)dest > ((int)src+count)) || (dest < src)) { while (bytelen--) *d++ = *s++; while (slice--) *(char *)d++ = *(char *)s++; } else /* overlap重叠 */ { d = (unsigned int*)((unsigned int)dest + count - 4); /*指针位置从末端开始,注意偏置 */ s = (unsigned int*)((unsigned int)src + count -4); while (bytelen --) *d-- = *s--; d++;s++;char * d1=(char *)d;char * s1=(char *)s;d1--;s1--;while (slice --) *(char *)d1-- = *(char *)s1--; } return dest;
}
对比一下,测试代码如下:
int main(){char a[20]="1133224466558877990";
// Memcpy1(a+2,a,5);
// Memcpy2(a+2,a,5);Memcpy(a+2,a,5);cout<<a<<endl;cin.get();
}
运行结果:
Memcpy1:
1111333466558877990
Memcpy2:
1111332466558877990
Memcpy:
1111332466558877990
后两种方法正确,第一种方法拷贝时无法规避内存重叠的bug。
实现一个高效率的内存拷贝函数memcpy相关推荐
- 字符串复制函数strncpy()和内存拷贝函数memcpy()
#include<string.h> char *strncpy(char *dest, const char *src, unsigned long n); 功能是将指针变量src所指向 ...
- 内存拷贝函数memcpy相关解析(C语言)
memcpy方法解析 内存拷贝函数的一般用法 memcpy()函数的拷贝原理分析 以深浅拷贝为例分析memcpy的拷贝原理 用memcpy()函数与不用memcpy()函数进行拷贝数据的区分 内存拷贝 ...
- C/c++中内存拷贝函数memcpy详解
原型:void*memcpy(void*dest, const void*src,unsigned int count); 功能:由src所指内存区域复制count个字节到dest所指内存区域. 说明 ...
- 内存拷贝函数memcpy
void* __cdecl memcpy(_Out_writes_bytes_all_(_Size) void* _Dst,_In_reads_bytes_(_Size) void const* _S ...
- 手撕内存拷贝函数 memmove、memcpy
做题家系列 -- 手撕内存拷贝函数 memmove.memcpy memcpy 函数原型 实现思路 手撕代码 面试注意要点 memmove 函数原型 实现思路 手撕代码 面试注意要点 总结 memcp ...
- 【C语言】字符串拷贝函数(strcpy)与内存拷贝函数的不同及内存拷贝函数(memcpy)的模拟实现
目录 字符串拷贝函数(strcpy) 函数原型 应用实例 我们将一个存放"abcdefg"的字符数组arr的内容拷贝到字符数组brr之中. 缺点 内存拷贝函数(memcpy) 函数 ...
- 【内存拷贝函数:memcpy与memmove】
文章目录 前言 一.memcpy函数(内存拷贝)的实验 二.memcpy函数的模拟实现 三.memmove函数(内存移动)的实验 四.memmove函数的模拟实现 总结 前言 c和c++使用的内存拷贝 ...
- c语言内存复制函数,【C语言】 字符串操作函数及内存拷贝函数归总
今天在这里把零散的一些常用的字符串操作函数和内存拷贝函数进行一下归总实现. 一 . 字符串操作函数 字符串操作函数有很多,这里我列举一些常用的函数,以及自实现的代码: 字符串拷贝函数: 函数原型:ch ...
- 字符串拷贝函数memcpy()、strncpy()和snprintf()性能之比较
问题: 函数memcpy(dest, src, sizeof(dest)).strncpy(dest, src, sizeof(dest))和snprintf(dest, sizeof(dest), ...
最新文章
- [转]实现Python HTTP服务方法大总结
- python中的选择结构语句是语句_python3控制语句---选择结构语句
- python constructor_python – 无法成功启动boa-constructor
- Command_Of_Windows1
- 前端教程分享:HTTP请求Content-Type你知道是做什么的吗?
- html中加入一个计时器,向html中的计时器添加毫秒
- 浅论ViewState及其与Session的关系
- mysql中用完即删用什么_MySQL使用和操作总结(《MySQL必知必会》读书笔记)
- AsyncTask理解- Day36or37
- 大型情感剧集Selenium:6_selenium中的免密登陆与cookie操作 #华为云·寻找黑马程序员#
- github客户端与git使用指南
- 项目1 :家庭记账系统
- 软考中级网络工程师的就业前景以及考试要求
- phpstudy+TP5隐藏入口文件
- OSPF NBMA网络
- JavaScript 可能问到的零星知识点
- 计算文本大小,将汉字转拼音
- 实习生招聘丨DolphinDB星臾计划
- Linux FrameBuffer(一) —— FrameBuffer是什么?怎么用?
- [agc012e]Camel and Oases
热门文章
- 【计算机网络】HTTPS 协议详解
- abcde依次进入一个队列_一个队列的入队序列为:abcde,则队列的出队序列是( )。
- Web前端需要学习什么?小白入门指南
- 世界上第一台计算机的速度,计算机IBM的蓝色基因(BlueGene/L),速度是世界上第一台电子计算机ENIAC的()倍...
- 放大格局!看AI如何助力软硬件智能化升级
- windows10永久禁用驱动强制签名
- 程序员听音乐——古典音乐
- 免费电子书下载 网站
- $.ajax与$.getJson的区别
- kali linux WiFi钓鱼