程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 面試:實現內存復制函數

面試:實現內存復制函數

編輯:C++入門知識

面試中面試官經常會讓寫程序,根據題目的難度會在算法和編程習慣上各有側重。比如寫一個memcpy函數,這個題算法簡單明確,因此重點考察編程習慣、工程思想。
該題目的算法如下
0.1
[cpp] 
void  memcpy(void *dst, void *src, int count) 

    while(count--) 
    { 
        *dst = *src; 
        dst++; 
        src++; 
    } 

問題是void*不能直接累加 *dst = *src也是不對的。
0.2
[cpp] 
void memcpy(void *dst, void *src, int count) 

    unsigned char *pdst = (unsigned char *)dst; 
    unsigned char *psrc = (unsigned char *)src; 
    while(count--) 
    { 
        *pdst = *psrc; 
        pdst++; 
        psrc++; 
    } 

在32位系統中,可復制的最多內存是多少?類型會不會不夠用?
內存復制不應該修改原始內存吧。
因此,函數聲明修改如下
0.3
[cpp]
void memcpy(void *dst, const void *src, size_t count) 
這樣就萬事大吉了嗎?
如果傳入了空指針呢?
接著修改吧
0.4
[cpp] 
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)。如果降低要求,可以修改原始數據完成復制,那麼這樣的設計能實現麼?這裡有一個版本可供參考。但是這樣的實現使得函數的功能不明確,可以認為是一種異常情況。
因此
0.5
[cpp]
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++; 
    } 

到這裡實現已經比較健壯了。有些人想要鏈式的調用函數,也就是復制完內存後,返回值直接當做其他函數的參數。
[cpp]
void * memcpy(void *dst, const void *src, size_t count) 
0.6因此最終版本為
[cpp] 
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; 

最後,有網友做了性能測試,結論顯示上面的實現達不到庫函數的性能。個人認為庫函數可能做了優化,例如使用mmx技術,使得一次復制一個字節到一次復制多個字節。


這個題目在面試出現的次數太頻繁,能夠比較正確的寫出這個函數的能說明什麼呢?
1.缺乏項目經驗,對於面試因此復習的很到位。
2.有可能有豐富的項目經驗,在項目中也這麼做。
3.認為有較多項目經驗,但是沒有注意非功能性要求。等著杯具

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved