码迷,mamicode.com
首页 > 编程语言 > 详细

C/C++ Prime学习要点1——实现memcpy库函数

时间:2015-08-04 09:26:23      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:memcpy   memmove   c库函数   

实现一个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;
}


C/C++ Prime学习要点1——实现memcpy库函数

标签:memcpy   memmove   c库函数   

原文地址:http://blog.csdn.net/tommyzht/article/details/47271525

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!