內存移動-很容易混亂的題

內存移動的問題重點在於考慮內存重疊的區域處理。這是對內存地址空間和處理問題能力的綜合考驗。
我今天就遇到了這樣一道面試題:重寫strcpy(),題目是這樣定義函數的:
char *strcpy(char *strDest, const char *strSrc);
要是以前對於我來說,直接就會這樣寫了:
char *strcpy(char *strDest, const char *strSrc)
{
          int len = strlen(strSrc);
          char *ret = strDest;
          if(strDest == NULL || strSrc == NULL || strDest == strSrc)
                 return strDest; 
          while(len-- != 0)
                 *strDest++ = *strSrc++;
                 *strDest = '\0';
          return ret;
}
但是現在我們要很認真地分析這個問題:
我們可以分成兩部分來做,每一部分都考慮它的最極端的情況,根據這兩種極端情況,我們可以對他們作出相應的處理。
(1)這種情況是strDest > strSrc, 但是strDest < strSrc+len-1.其中len=strlen(strSrc).用圖形更好看:(地址從下往上:低到高)
假設strSrc 指向的內容是 "hello";
                                              .
                                              .
                                              .
                                              .
                                              \0
                                              o
                                              l
                                              l
    strDest                                   e
    strSrc                                    h               

這種情況對於剛開始的那段程序顯然結果是錯誤的。最後返回的是“hhhhh”。
這種強況強烈建議使用從末尾向開頭的順序複製,代碼如下:
if(strDest > strSrc && strDest < (strSrc + len + 1)){
             strDest = strDest + len -1;
             strSrc  = strSrc  + len -1;
             *(strDest+1) = '\0';
             while(len-- != 0)
                   *strDest-- = *strSrc--;
             return strDest;
}
其它情況我們可以很放心地進行從前向後的複製了,而且如果是以下這種情況我們必須從前向後複製:
                                                                  
                                                  .    
                                                  .
                                                  .
                                                  \0
                                                  o 
                                                  l
                                                  l
 strSrc                                           e
 strDest                                          h  
即strDest<strSrc,這種情況我們一旦使用從後向前複製的話,就會是這樣的結果:"ooooo".上面if的條件除外的其它條件是:
strDest < strSrc || strDest >= (strSrc + len +1).而這兩種情況我們都可以使用從開頭向末尾進行復制。代碼如下:
else{
      char *ret = strDest;
      len = strlen(strSrc);
      while(len-- != 0){
               *strDest++ = *strSrc++;
      }
      *strDest = '\0';
      return ret;
}
這樣所用的情況都有了。在複製過程中就完全正確了!
下面是對以上問題的總結,方便記住什麼情況我們該怎麼做:
只要strDest(目標地址)在strSrc(源地址)的範圍內,我們就使用從後向前複製即可。其它情況從前向後複製即可!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章