1. 程式人生 > >編寫memcpy函式

編寫memcpy函式

memcpy函式,這個題演算法簡單明確,因此重點考察程式設計習慣、工程思想。 該題目的演算法如下 

void  memcpy(void *dst, void *src, int count) 

{  

while(count--)     

 

         *dst = *src; 

         dst++; 

         src++;  

  }  

}  

32位系統中,可複製的最多記憶體是多少?型別會不會不夠用?記憶體複製不應該修改原始記憶體吧。 

因此,函式宣告修改如下 void memcpy(void *dst, const void *src, size_t count)  

這樣就萬事大吉了嗎?如果傳入了空指標呢? 接著修改吧 

void memcpy(void *dst, const void *src, size_t count)

 {  

     assert(dst != NULL);  

     assert(src != NULL);  

   

 unsigned char *pdst = (unsigned char *)dst;  

     const unsigned char *psrc = (const unsigned char *)src; 

     while(count--)      

    {  

         *pdst = *psrc;  

          pdst++;      

        psrc++;     

  

如果有這樣的陣列char ina[]={0,1,2,3,4,5,6,7,8,9,10,11}; 進行如下呼叫memcpy(&ina[1], &ina[0], 5);會發生什麼情況?由於原始資料和目的資料在空間上存在重疊,這樣導致複製過程中不可避免會對原始資料做修改。而這樣的修改在函式的宣告中是看不到的(const void *src)。如果降低要求,可以修改原始資料完成複製,那麼這樣的設計能實現麼?這裡有一個版本可供參考。但是這樣的實現使得函式的功能不明確,可以認為是一種異常情況。 

void memcpy(void *dst, const void *src, size_t count)  

{  

       assert(dst != NULL); 

     assert(src != NULL);  

       unsigned char *pdst = (unsigned char *)dst;  

       const unsigned char *psrc = (const unsigned char *)src;  

       assert(!(psrc<=pdst && pdst<psrc+count));//判斷是否有重疊 

       assert(!(pdst<=psrc && psrc<pdst+count));  

      while(count--) 

     

         *pdst = *psrc; 

          pdst++;  

          psrc++;  

     }

 }  

到這裡實現已經比較健壯了。有些人想要鏈式的呼叫函式,也就是複製完記憶體後,返回值直接當做其他函式的引數。 

void * memcpy(void *dst, const void *src, size_t count)  最終版本為 

void* memcpy(void *dst, const void *src, size_t count)  

{  

     assert(dst != NULL);  

     assert(src != NULL);  

     unsigned char *pdst = (unsigned char *)dst;  

     const unsigned char *psrc = (const unsigned char *)src;

     assert(!(psrc<=pdst && pdst<psrc+count));

     assert(!(pdst<=psrc && psrc<pdst+count)); 

     while(count--) 

     {  

         *pdst = *psrc; 

         pdst++;

         psrc++; 

     } 

    return dst;

 }