C/C++ Prime学习要点1——实现memcpy库函数
2015-08-04 09:16
483 查看
实现一个Memcpy函数。
Memcpy函数用于 把资源内存(src所指向的内存区域) 拷贝到目标内存(dest所指向的内存区域);
拷贝多少个?有一个size变量控制拷贝的字节数。
函数原型:void *memcpy(void *dest, void *src, unsigned int count);
用法:(1)可以拷贝任何类型的对象,因为函数的参数类型是void*(未定义类型指针),也就是说传进去的实参可以是int*,short*,char*等等,
但是由于函数拷贝的过程是一个字节一个字节的拷贝的,所以实际操作的时候要把void*强制转化为char*,这样在指针加的时候才会保证每次加一个字节。
一开始我们很可能写出如下错误代码:
上面错误代码原因:
函数原型应该是 void*memcpy(void* dest,const void* src,size_t count)
按照ANSI(American National Standards Institute)标准,不能对void指针进行算法操作,即不能对void指针进行如p++的操作,所以需要转换为具体的类型指针来操作,例如char *。
memcpy是对内存进行操作,可能遇到内存重叠的情况,同样的问题存在于memmove中, 但是源代码中这两个函数的处理方式不一样:memcpy中dest和source中的区域不能重叠,否则会出现未知结果中dest和source中的区域重叠,否则会出现未知结果。函数没做任何内存的处理,内存是否重叠由程序员自己控制。memmove里面则判断了内存重叠的情况,当内存重叠时从后往前复制,以确保复制正常处理。
考虑内存重叠情况:
1、若没有内存重叠,则从低地址往高地址复制
2、若有内存重叠,则从高地址往低地址复制
代码如下:(这其实也是memmove代码)
memcpy 与 memmove区别:
memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下:
void *memcpy(void *dst, const void *src, size_t count);
void *memmove(void *dst, const void *src, size_t count);
作用是一样的,唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确。
情况一,拷贝重叠的区域不会出现问题,内容均可以正确的被拷贝。
情况二,问题出现在右边的两个字节,这两个字节的原来的内容首先就被覆盖了,而且没有保存。所以接下来拷贝的时候,拷贝的是已经被覆盖的内容,显然这是有问题的。
实际上,memcpy只是memmove的一个子集。
memcpy没有考虑内存重叠的实现方法:
Memcpy函数用于 把资源内存(src所指向的内存区域) 拷贝到目标内存(dest所指向的内存区域);
拷贝多少个?有一个size变量控制拷贝的字节数。
函数原型:void *memcpy(void *dest, void *src, unsigned int count);
用法:(1)可以拷贝任何类型的对象,因为函数的参数类型是void*(未定义类型指针),也就是说传进去的实参可以是int*,short*,char*等等,
但是由于函数拷贝的过程是一个字节一个字节的拷贝的,所以实际操作的时候要把void*强制转化为char*,这样在指针加的时候才会保证每次加一个字节。
一开始我们很可能写出如下错误代码:
void memcpy(void *dest, void *src, int len) { void *p = dest; void *q = src; if( dest == NULL ||src == NULL) { return; } for (int i=0; i<len; i++) { *p++ = *q++; } }
上面错误代码原因:
函数原型应该是 void*memcpy(void* dest,const void* src,size_t count)
按照ANSI(American National Standards Institute)标准,不能对void指针进行算法操作,即不能对void指针进行如p++的操作,所以需要转换为具体的类型指针来操作,例如char *。
memcpy是对内存进行操作,可能遇到内存重叠的情况,同样的问题存在于memmove中, 但是源代码中这两个函数的处理方式不一样:memcpy中dest和source中的区域不能重叠,否则会出现未知结果中dest和source中的区域重叠,否则会出现未知结果。函数没做任何内存的处理,内存是否重叠由程序员自己控制。memmove里面则判断了内存重叠的情况,当内存重叠时从后往前复制,以确保复制正常处理。
考虑内存重叠情况:
1、若没有内存重叠,则从低地址往高地址复制
2、若有内存重叠,则从高地址往低地址复制
代码如下:(这其实也是memmove代码)
void *memcpy(void *dst, const void *src, size_t len) { if(NULL == dst || NULL == src){ return NULL; } void *ret = dst; if(dst <= src || (char *)dst >= (char *)src + len){ //没有内存重叠,从低地址开始复制 while(len--){ *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } }else{ //有内存重叠,从高地址开始复制 src = (char *)src + len - 1; dst = (char *)dst + len - 1; while(len--){ *(char *)dst = *(char *)src; dst = (char *)dst - 1; src = (char *)src - 1; } } return ret; }
memcpy 与 memmove区别:
memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下:
void *memcpy(void *dst, const void *src, size_t count);
void *memmove(void *dst, const void *src, size_t count);
作用是一样的,唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确。
情况一,拷贝重叠的区域不会出现问题,内容均可以正确的被拷贝。
情况二,问题出现在右边的两个字节,这两个字节的原来的内容首先就被覆盖了,而且没有保存。所以接下来拷贝的时候,拷贝的是已经被覆盖的内容,显然这是有问题的。
实际上,memcpy只是memmove的一个子集。
memcpy没有考虑内存重叠的实现方法:
void *memcpy(void *dest, const void *src, unsigned int count) { assert((dest != NULL) && (src != NULL)); void *address = dest; while (count --) { *(char *) dest = *(char *) src; dest = (char *) dest + 1; src = (char *) src + 1; } return address; }
相关文章推荐
- oj 中G++和C++区别
- C语言文件操作
- C++实现简单的职工信息管理系统
- C++、 C 中的结构体、联合和枚举 异同
- 设计模式C++学习笔记之十九(State状态模式)
- 设计模式C++学习笔记之十八(Visitor访问者模式)
- 设计模式C++学习笔记之十七(Chain of Responsibility责任链模式)
- 设计模式C++学习笔记之十六(Observer观察者模式)
- 设计模式C++学习笔记之十五(Composite组合模式)
- 设计模式C++学习笔记之十四(Iterator迭代器模式)
- 设计模式C++学习笔记之十三(Decorator装饰模式)
- 设计模式C++学习笔记之十二(Command命令模式)
- 设计模式C++学习笔记之十一(Bridge桥梁模式)
- 《C++ Primier Plus》02
- 设计模式C++学习笔记之十(Builder建造者模式)
- 设计模式C++学习笔记之九(Template Method模板方法模式)
- 设计模式C++学习笔记之八(Adapter适配器模式)
- 设计模式C++学习笔记之七(AbstractFactory抽象工厂模式)
- 设计模式C++学习笔记之六(Facade门面模式)
- 设计模式C++学习笔记之五(Factory Method工厂方法模式)