其实这个问题大致的意思就是让你写一个函数,这个函数有三个参数:需要移动的指针地址void *src,目的地地址void*dest,以及内存的字节长度len。让你将src中的内容移动到dest中。

      之所以总结这个,是因为在面试腾讯的实习时,两次被问到这个问题,在一面的时候面试官挺耐心的,因为我没听过这个(虽然很基础),他就很细心地讲解,然后让我写出自己的思路;在二面的时候另一个面试官让我把代码写出来,结果我写得很复杂,就跪了。。。

      其实在一面之后,我有回去百度看了下这个函数,但是因为自己知道了在内存移动的时候会出现什么情况,就没看代码实现(自大啊。。。),后来就吃亏了。

 

分析:

         对于内存移动,首先要考虑:destsrc是不是指向同一内存地址。在这种情况下,就不需要进行任何实际的移动了,如图所示:

         其次,我们要考虑两个指针指向的len长度的内存会不会有重叠,如果有重叠的话,直接进行移动有可能会破坏原始数据(在还没移动之前):

 

 

         在情况2中,destsrc的右边(dest的地址值比src大),且destsrc之间的长度比len小,在这种情况下,如果直接从低地址往高地址复制,那么从dest开始的位置到src+len位置的数据将会被破坏。

         在情况3中,因为destsrc的距离大于len,所以不会出现重叠的情况。

 

         在情况4中,dest的地址值比src小(即destsrc的左边),如果srcdest的距离比len小,虽然会出现重叠的情况,但是却不会造成数据的损坏。因为重叠那部分数据在被替换前已经被移走。因此在这种情况下,不管destsrc之间的距离是多大,从低地址向高地址移动是没有问题的。

 

代码实现:

         在面试的时候,我傻傻地把所有情况都用一个if来做判断,然后用几个指针来避免数据破坏,其实,并不需要这么麻烦。

         destsrc的左边(即dest的地址值比src的小)时,只需要从左往右赋值(即从低地址开始复制);当destsrc的右边(即dest的地址值比src的大),只需要从右往左开始赋值就行了(即从高地址开始复制)。使用这种方法,即使发生重叠,也能避免数据的破化。

 1 void* MyMemMove(void *dest, const void *src, size_t nBytes){
 2     void *ret = dest;           //用于返回
 3 
 4     const char *from = static_cast<const char*>(src);
 5     char *to   = static_cast<char*>(dest);
 6  
 7     if( dest < src ){                   //dest在src的左边
 8         while( nBytes-- )        //从左往右复制
 9             *to++ = *from++;
10     }else if( dest > src ){                  //dest在src的右边
11         from += nBytes - 1;      //从右往左复制
12         to   += nBytes - 1;
13         while( nBytes-- )
14             *to-- = *from--;
15     }
16     return ret;
17 }  

 

      写完之后,在博客园看到这篇写得挺简洁的,推荐一下:http://www.cnblogs.com/kekec/archive/2011/07/22/2114107.html

 

posted on 2015-04-10 20:57  程序员的猫  阅读(3302)  评论(0编辑  收藏  举报