关于C函数memcpy的实现细节思考
来源:互联网 发布:屏蔽他人手机信号软件 编辑:程序博客网 时间:2024/05/21 11:08
前段时间和朋友讨论关于C基础函数memcpy的实现细节时,收获颇多。这个函数在C / C++编程领域中使用率是比较高的(可能排在前10左右)。但鲜有人去研究其实现原理。为了弄清楚其实现,我给自己出了一道题目,就是用C实现一个memcpy的函数。先看标准memcpy函数的参数和返回值:
void* memcpy(void* dst, void* src, size_t size);dst - 目的内存地址,src - 源内出地址,size- 需要复制的长度。返回值为dst。
初想一下,这个函数很简单,就随手写了一个实现。如下:
void* my_memcpy(void *dst, const void* src, size_t size){if(dst == NULL || src == NULL || size <= 0)return dst;char* dst_pos = (char *)dst;char* src_pos = (char *)src;while(size > 0){*dst_pos++ = *src_pos++;size --;}return dst;}咋一看,这个函数是正确的。我使用了基本的测试代码如下:
int main(int argc, char* argv[]){unsigned char buf[15] = {0};unsigned char dst_buf[15] = {0};for(unsigned char i = 3; i < 13; i ++)buf[i] = i;printf("src buf = ");for(int i = 0; i < 15; i ++)printf("%d ", buf[i]);printf("\r\n");//不同BUFF之间拷贝my_memcpy(dst_buf, buf, 15);printf("from buf copy to dst buf, dst_buf = ");for(int i = 0; i < 15; i ++)printf("%d ", dst_buf[i]);//同一个BUFF向后拷贝my_memcpy(buf + 4, buf + 3, 10);printf("\nfrom buf + 3 copy to buf + 5, buf =");for(int i = 0; i < 15; i ++){printf("%d ", buf[i]);buf[i] = 0;}//同一个BUFF向前拷贝for(unsigned char i = 3; i < 13; i ++)buf[i] = i;my_memcpy(buf, buf + 3, 10);printf("\nfrom buf + 5 coy to buf, buf = ");for(int i = 0; i < 15; i ++)printf("%d ", buf[i]);return 0;}
如果用上测试用例来测试,上面写的my_memcpy是只能过不同buf之间的拷贝和同一BUF向前拷贝,同一buf向后拷贝的情况重叠内存是被覆盖了的。于是我进行了修改:
void* my_memcpy(void *dst, const void* src, size_t size){if(dst == NULL || src == NULL || size <= 0)return dst;char* dst_pos = (char *)dst + size;char* src_pos = (char *)src + size;while(size > 0){*dst_pos-- = *src_pos--;size --;}return dst;}
从上可以看出,我做了向前拷贝兼容,防止向后拷贝重叠地址被覆盖的情况。但第三种情况向前拷贝的重叠内存还是被覆盖了。这就要思考根据参数判断是从前拷贝还是从后拷贝。于是修改为:
void* my_memcpy(void *dst, const void* src, size_t size){if(dst == NULL || src == NULL || size <= 0)return dst;char* dst_pos = (char *)dst;char* src_pos = (char *)src;if(dst_pos < src_pos + size && dst > src){ //DOWN COPY,向前拷贝dst_pos = dst_pos + size;src_pos = src_pos + size;while(size > 0){*dst_pos-- = *src_pos--;size --;}}else { //UP COPY,向后拷贝while(size > 0){*dst_pos++ = *src_pos++;size --;}}return dst;}这个实现是兼容向前拷贝和向后拷贝、不同BUF拷贝的情况,也近似C函数库的实现。后来我跟踪了下C函数库的实现,它是用ASM进行实现的。我贴出VC++中的实现:
ifdef MEM_MOVE _MEM_ equ <memmove>else ; MEM_MOVE _MEM_ equ <memcpy>endif ; MEM_MOVE% public _MEM__MEM_ proc \ dst:ptr byte, \ src:ptr byte, \ count:IWORD ; destination pointer ; source pointer ; number of bytes to copy; push ebp ;U - save old frame pointer; mov ebp, esp ;V - set new frame pointer push edi ;U - save edi push esi ;V - save esi mov esi,[src] ;U - esi = source mov ecx,[count] ;V - ecx = number of bytes to move mov edi,[dst] ;U - edi = dest;; Check for overlapping buffers:; If (dst <= src) Or (dst >= src + Count) Then; Do normal (Upwards) Copy; Else; Do Downwards Copy to avoid propagation;
..........后面的ASM代码太长,我没有全部给出。它也是做了情况判断,只是整个实现考虑的情况很多,细节考虑的很多。所以,通过对memcpy函数的分析,我们可以很好的了解内存操作需要注意的地方,尤其是同一buf向前拷贝和向后拷贝的问题,我们不仅仅要会使用API,更需要弄清楚API背后的逻辑。
0 0
- 关于C函数memcpy的实现细节思考
- 3、C函数可变参数实现细节的一些思考
- 【C语言】memcpy函数的实现
- memcpy/memset函数的c语言实现
- memcpy/memset函数的c语言实现
- C/C++--memcpy函数实现
- memcpy函数的实现
- memcpy函数的实现
- memcpy函数的实现
- memcpy函数的实现
- 实现c中memcpy函数
- 内存拷贝函数(memcpy)的深入思考
- 关于C语言字符串函数的思考
- 关于C语言字符串函数的思考
- C语言中变参函数的实现细节
- C基础:strcat,strcmp,memcpy,strcpy等函数的实现
- C 标准库 memcpy and memmove 函数的实现
- C语言 string及memcpy,memmove函数的模拟实现
- Tomcat7.0配备,解决点击startup.bat后闪退的情况
- 哈哈,程序猿
- easyui validatebox 验证集合
- 淘宝技术发展(Java时代:创造技术-TFS)
- Linux学习之CentOS(十三)--CentOS6.4下Mysql数据库的安装与配置
- 关于C函数memcpy的实现细节思考
- Word2010中不显示MathType选项卡解决办法
- 红黑树的读书笔记
- Got a packet bigger than ‘max_allowed_packet’ bytes的解决方法
- oracle表分区详解
- VS2010 旗舰版 MFC开发 调试断点无效的解决办法
- Xcode 5 静态库的制作打包与使用
- 2014-第八周项目二-时间类的运算符重载
- Apache负载均衡+tomcat