內存移動(memmove)


      其實這個問題大致的意思就是讓你寫一個函數,這個函數有三個參數:需要移動的指針地址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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM