关于实现memcpy和memmove两个库函数的一点体会

来源:互联网 发布:直销矩阵制示意图 编辑:程序博客网 时间:2024/05/21 04:43

最近在论坛上看了一篇关于阿里巴巴面试题的帖子,让自己实现memcpy库函数,要求考虑特殊情况,两段内存存在覆盖,以及指针为空的情况。下面是我对此问题的几点看法(可能还有理解不到的地方)和最终修改的代码。


几点结论: 
1,memcpy实现从源source中拷贝n个字节到目标destin中,src源数据应该保留。
2,memmove实现移动一块字节,src源数据可以不保留。
3,memcpy没有考虑内存覆盖问题(由assert条件可知);而memmove考虑了内存覆盖问题,并给出了解决办法。
4,memcpy和memmove中不需要考虑数组越界问题,dst的长度应该大于src的长度,这是调用者应该考虑的问题。


  1. /*  
  2.  * 函数名: memcpy  
  3.  * 功  能: 从源source中拷贝n个字节到目标destin中  
  4.  * 用  法: void *memcpy(void* destin, const void* source, size_t n);  
  5.  * 说  明: 自己实现此库函数 
  6. */  
  7. #include <stdio.h>   
  8. //#include <string.h>//memcpy库函数头文件  
  9. #include <conio.h>   //getch头文件  
  10. #include <assert.h>  //assert头文件  
  11. typedef unsigned char byte;   
  12. //typedef unsigned int size_t;  
  13.   
  14. /* 
  15. memcpy自定义函数 
  16. */  
  17. //src要保留  
  18. void* memcpy(void* dst,const void* src,size_t count)   
  19. {  
  20.     char* pbTo = (char*)dst;   
  21.     char* pbFrom = (char*)src;   
  22.     assert(dst!= NULL && src != NULL);//不能存在空指针  
  23.     assert(pbTo >= pbFrom+count || pbFrom >= pbTo + count);//防止内存重叠(overlap)   
  24.     while (count-- > 0)   
  25.     {   
  26.         *pbTo++ = *pbFrom++;   
  27.     }   
  28.     return dst;   
  29. }  
  30. /* 
  31. memmove自定义函数 
  32. */  
  33. //src可以不保留  
  34. void* memmove(void* dst,const void* src,size_t count)   
  35. {     
  36.     char* pbTo = (char*)dst;   
  37.     char* pbFrom = (char*)src;   
  38.     assert(dst != NULL && src != NULL);//不能存在空指针  
  39.     if (dst <= src || pbTo >= pbFrom + count)//没有overlap的情况,直接拷贝   
  40.     {   
  41.         while (count-- > 0)   
  42.         {   
  43.             *pbTo++ = *pbFrom++;   
  44.         }   
  45.     }   
  46.     else   
  47.     {   
  48.         pbTo = pbTo + count -1;//overlap的情况,从高位地址向低位拷贝   
  49.         pbFrom = pbFrom + count -1;   
  50.         while (count-- > 0)   
  51.         {   
  52.             *pbTo-- = *pbFrom--;   
  53.         }   
  54.     }   
  55.     return dst;   
  56. }  
  57. int main()  
  58. {  
  59.     char src[]="*********";  
  60.     char dst[]="abcdefghijklmnopqrstuvwxyz";  
  61.     char *ptr;  
  62.     printf("destination before memcpy: %s/n",dst);  
  63.       
  64.     //测试用例1  
  65.     ptr=(char *)memcpy(dst,src,sizeof(src)/sizeof(char));  
  66.     //测试用例2  
  67.     //ptr=(char *)memmove(dst,src,sizeof(src)/sizeof(char));  
  68.     //测试用例3  
  69.     //ptr=(char *)memcpy(dst+1,dst,2);//memcpy没有考虑内存覆盖,如果出现覆盖assert报错  
  70.     //测试用例4  
  71.     //ptr=(char *)memmove(dst+1,dst,2);//memmove考虑了内存覆盖  
  72.     if (ptr)  
  73.     {  
  74.         printf("destination after memcpy: %s/n",ptr);  
  75.     }  
  76.     else  
  77.     {  
  78.         printf("memcpy failed/n");  
  79.     }  
  80.       
  81.     getch();  
  82.     return 0;  
  83. }  


修改用例测试:

  1. /* 
  2. Modification Date: 2010-3-17   
  3. Author: wcdj 
  4. */  
  5. #include <cstdio>      
  6. #include <string.h>   // memcpy库函数头文件     
  7. #include <conio.h>    // getch头文件     
  8. #include <assert.h>   //assert头文件   
  9. typedef unsigned char byte;      
  10. //typedef unsigned int size_t;  
  11. /*   
  12. memcpy自定义函数   
  13. */    
  14. //src要保留     
  15. void* memcpy(void* dst,const void* src,size_t count)      
  16. {     
  17.     char* pbTo = (char*)dst;      
  18.     char* pbFrom = (char*)src;      
  19.     assert(dst!= NULL && src != NULL);//不能存在空指针     
  20.     assert(pbTo >= pbFrom+count || pbFrom >= pbTo + count);//防止内存重叠(overlap)      
  21.     while (count-- > 0)      
  22.     {      
  23.         *pbTo++ = *pbFrom++;      
  24.     }      
  25.     return dst;      
  26. }     
  27. /*   
  28. memmove自定义函数   
  29. */    
  30. //src可以不保留     
  31. void* memmove(void* dst,const void* src,size_t count)      
  32. {        
  33.     char* pbTo = (char*)dst;      
  34.     char* pbFrom = (char*)src;      
  35.     assert(dst != NULL && src != NULL);//不能存在空指针     
  36.     if (dst <= src || pbTo >= pbFrom + count)//没有overlap的情况,直接拷贝      
  37.     {      
  38.         while (count-- > 0)      
  39.         {      
  40.             *pbTo++ = *pbFrom++;      
  41.         }      
  42.     }      
  43.     else      
  44.     {      
  45.         pbTo = pbTo + count -1;//overlap的情况,从高位地址向低位拷贝      
  46.         pbFrom = pbFrom + count -1;      
  47.         while (count-- > 0)      
  48.         {      
  49.             *pbTo-- = *pbFrom--;      
  50.         }      
  51.     }      
  52.     return dst;      
  53. }     
  54. int main()     
  55. {     
  56.     // test  
  57.     char src[]="123456";     
  58.     char dst[]="abcdefghijklmnopqrstuvwxyz";     
  59.     char *ptr;     
  60.       
  61.     printf("destination before memcpy: %s/n",dst);     
  62.       
  63.     //测试用例1     
  64.     ptr=(char *)memcpy(dst,src,sizeof(src)/sizeof(char));// "123456"    
  65.     //ptr=(char *)memcpy(dst,src,strlen(src));// "123456ghijklmnopqrstuvwxyz"  
  66.     //测试用例2     
  67.     //ptr=(char *)memmove(dst,src,sizeof(src)/sizeof(char));// "123456"    
  68.     //ptr=(char *)memmove(dst,src,strlen(src));// "123456ghijklmnopqrstuvwxyz"  
  69.     //测试用例3     
  70.     //ptr=(char *)memcpy(dst+1,dst,2);//memcpy没有考虑内存覆盖,如果出现覆盖assert报错     
  71.     //测试用例4     
  72.     //ptr=(char *)memmove(dst+1,dst,2);//memmove考虑了内存覆盖 "abde...z"     
  73.       
  74.     if (ptr)     
  75.     {     
  76.         printf("destination after memcpy: %s/n",ptr);     
  77.     }     
  78.     else    
  79.     {     
  80.         printf("memcpy failed/n");     
  81.     }     
  82.       
  83.     getch();     
  84.     return 0;     
  85. }  

0 0
原创粉丝点击