昨天被問了個很基礎的C語言的問題。
寫出u8 * memcpy(u8 * src, u8 * dst, size_t len)的定義。
比較緊張,以為要考慮很多東西;於是,將很多亂七八糟的情況考慮了下。
一般寫成void *,強制轉換成8bit的類型。事實上,由於這裡使用unsigned char型,不再需要強制轉換了。
src和dst是否為空白,我用if判斷。如果src空,則出錯;dst空,當時想到怎樣解決這個問題。
如果在這裡為dst申請空間,那麼由誰來釋放?
由於容易造成記憶體流失,被調用函數申請空間不可取,因此還是直接報錯。申請空間的責任應該由調用者負擔,同時由他回收,確保記憶體安全。
可以設定assert:
assert(dst != NULL || src != NULL);
如果用
*src ++ = *dst ++;
需要另外定義一個指標,指向dst的首位元組,供返回指標使用。
也可以另外定義臨時變數,使用for迴圈
*(src + i) = *(dst + i);
這樣,dst沒變,直接返回。
如果src和dst在len長度下有覆蓋怎麼辦?
* src | |
* dst| |
事實上,在庫函數中,memcpy不能改變來源資料,此時應該報錯。
在memmove中,才可以覆蓋掉src。
但我還是根據他的指示,將重複區覆蓋了。
事實上,如果使用for迴圈的形式,可以直接從最後向前進行拷貝,不須覆蓋,結果總正確。由於拷貝是從最高位開始,這樣就保證src中還沒拷貝的塊不會因為dst的原因被修改。
如果調用庫函數memcpy()和memmove(),則要注意:
函數memcpy()從src指向的地區向dst指向的地區複製len個字元;如果兩數組重疊,不定義該函數的行為。
而memmove(),如果兩函數重疊,賦值仍正確進行。
memcpy函數假設要複製的記憶體地區不存在重疊,如果你能確保你進行複製操作的的記憶體地區沒有任何重疊,可以直接用emcpy;
如果你不能保證是否有重疊,並且源數組不再使用,為了確保複製的正確性,你必須用memmove。