函数实现-memcpy-strcpy-memmove-memset

1. 函数原型(c++ reference)

    void * memcpy ( void * destination, const void * source, size_t num );  不能解决某些覆盖问题。
    char * strcpy ( char * destination, const char * source ); 不能解决某些覆盖问题,根据'\0'表示字符串复制终止。
    void * memmove ( void * destination, const void * source, size_t num );  能够解决所有覆盖问题。
    void * memset ( void * ptr, int value, size_t num );  其中value使用int传入,但是被解释为unsigned char。 

 2. 重叠问题

    ·dest == src 不需要拷贝
    ·dest<src,无论有没有重叠,正向拷贝即可。
    ·dest>src,且dest>=src+len,没有重叠,正向拷贝即可。
    ·dest>src,且dest<src+len,有重叠,需要逆向拷贝。
     对于memcpy和strcpy,都是正向拷贝,不能处理第四种情况。
     对于memmove,考虑到所有的情况即可。
     对于memset,相对简单,就是赋值就可以了。

3. 代码

void *  memcpy( void *  dest, const   void *  src, size_t num) {  //  const
  assert((dest  !=  NULL)  &&  (src  !=  NULL)  &&  (dest != src));  //  assert
   char *  p_dest  =  ( char * )dest;  //  copy
   const   char *  p_src  =  ( const   char * )src;
  
while (num --   >   0 )
    
* p_dest ++   =   * p_src ++ ;
  
return  dest;  //  address
}
char *  strcpy( char *  dest,  const   char *  src) {
  assert((dest
!= NULL)  &&  (src != NULL)  &&  (dest != src));
  
char *  address  =  dest;
  
while (( * dest ++   =   * src ++ !=   ' \0 ' )
    NULL;
  
return  address; 
}
void *  memmove( void *  dest,  const   void *  src,size_t num) {
  assert((dest
!= NULL)  &&  (src != NULL)  &&  (dest != src));  
  
char *  p_dest  =  ( char * )dest;
  
const   char *  p_src  =  ( const   char * )src;
  
if (p_dest > p_src  &&  p_dest < p_src + num) {  // p_dest>p_src,逆向拷贝
    p_dest  +=  num  -   1 ;
    p_src 
+=  num  -   1 ;
    
while (num -- )
      
* p_dest --   =   * p_src -- ;     
  }
  
else  {  // p_dest<=p_src,此时无论是否重叠都可以使用正向拷贝
     while (num -- )
      
* p_dest ++   =   * p_src ++ ;
  }
  
return  dest;
}
void *  memset( void *  dest,  int  value, size_t num) {
  assert(dest 
!=  NULL);
  unsigned 
char *  p_dest  =  (unsigned  char * )dest;
  
while (num --   >   0
    
* p_dest ++   =  (unsigned  char )value;
  
return  dest;
}

 4. 其他

    这几个函数常被用来测试编程人员的编程风格。实际上,函数库中的这些函数实现都是汇编搞定的,要更多的考虑机器指令方面的问题,来使用汇编,效率会更高,这就先到这里了。

5. 关于size_t

    size_t是标准C库中定义的,应为unsigned int。 实际上,对于本文的一系列函数,msdn的函数原型都是用size_t,而linux内核往往使用int。
    原因如下吧:
  “数据类型"socklen_t"和int应该具有相同的长度。否则就会破坏 BSD套接字层的填充.POSIX开始的时候用的是size_t, Linus Torvalds(他希望有更多的人,但显然不是很多) 努力向他们解释使用size_t是完全错误的,因为在64位结构中 size_t和int的长度是不一样的,而这个参数(也就是accept函数的第三参数)的长度必须和int一致,因为这是BSD套接字接口标准.最终POSIX的那帮家伙找到了解决的办法,那就是创造了一个新的类型"socklen_t".Linux Torvalds说这是由于他们发现了自己的错误但又不好意思向大家伙儿承认,所以另外创造了一个新的数据类型 。
    在C++中,size_t的引入增强了程序在不同平台上的可移植性,经测试发现,在32位系统中size_t是4字节的,而在64位系统中,size_t是8字节的,这样利用该类型可以增强程序的可移植性。”

6. 参考资料

    C++ Reference    http://www.cplusplus.com/reference/clibrary/cstring/
    strcpy()、memcpy()、memmove()、memset()的实现    http://www.cnitblog.com/guopingleee/archive/2009/02/15/54581.html
    size_t 百度百科    http://baike.baidu.com/view/3236587.htm

你可能感兴趣的:(move)