关于memcpy

对于memcpy,网上对其的实现大多是简单的循环拷贝,如果拷贝的时候存在交叉,就可能出问题:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 void *memcpy(void *memTo, const void *memFrom, size_t size)
 7 {
 8   if((memTo == NULL) || (memFrom == NULL)) //memTo和memFrom必须有效
 9          return NULL;
10   char *tempFrom = (char *)memFrom;             //保存memFrom首地址
11   char *tempTo = (char *)memTo;                  //保存memTo首地址     
12   while(size -- > 0)                //循环size次,复制memFrom的值到memTo中
13          *tempTo++ = *tempFrom++ ; 
14   return memTo;
15 }
16 
17 int main() {
18     char name[10] = "123456";
19     //将字符串向后移一位
20     memcpy(name + 1, name, strlen(name) - 1);
21     printf("%s\n", name);
22     return 0;
23 }

程序输出的是“111111”,而不是112345。但是,如果调用系统的memcpy函数,确能得到正确的结果(环境:win7 64bit,visual 2008)。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 int main() {
 7     char name[10] = "123456";
 8     //将字符串向后移一位
 9     memcpy(name + 1, name, strlen(name) - 1);
10     printf("%s\n", name);
11     return 0;
12 }

程序输出的是112345。可见自带的memcpy已经能够正确实现交叉拷贝(虽然网上都说memcpy不能处理交叉时候的拷贝)。

所以,memcpy的实现到底是怎样的呢。对于void* memcpy(void *des, void *src, int n);

1.当des <= src的时候,字符串能够正确从左到右拷贝,因为des覆盖src的时候,src处的字符串已经没用了。

2.当des > src且des - src >= n时,复制的片段没有交叉,所以能够正常拷贝。

3.当des > src且des - src < n时,从左到右拷贝时,src中待拷贝的片段会被前面的覆盖掉,解决的办法是将拷贝的顺序改成从右向左。这样des覆盖src的时候,src处的字符串已经没用了,有点像1处的情况。

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 void *memcpy(void *des, const void *src, size_t size)
 7 {
 8     if((des == NULL) || (src == NULL))        
 9         return NULL;
10 
11     char *tempSrc, *tempDes;
12     if((unsigned char*)des <= (unsigned char*)src ||       //1.des <= src
13         (unsigned char*)des - (unsigned char*)src >= size) //2.des > src且des - src >= n
14     { 
15             tempSrc = (char *)src;               
16             tempDes = (char *)des;              
17             while(size -- > 0)                       
18                 *tempDes++ = *tempSrc++ ; 
19     } 
20     else {   //3.des > src且des - src < n                         
21         tempSrc = (char *)src + size - 1;
22         tempDes = (char *)des + size - 1;
23         while(size -- > 0) 
24             *tempDes -- = *tempSrc --;
25     }
26     return des;
27 }
28 
29 int main() {
30     char name[10] = "123456";
31     //memcpy(name, name + 1, strlen(name) - 1);  //1.des <= src
32     //memcpy(name + 3, name, 3);                 //2.des > src且des - src >= n
33     memcpy(name + 1, name, strlen(name) - 1);    //3.des > src且des - src < n
34     printf("%s\n", name);
35     return 0;
36 }

 

posted on 2014-04-09 10:13  CrazyAC  阅读(198)  评论(0编辑  收藏  举报