每天一個開發小知識。面試中,我們可能遇到過讓你實作 memcpy 函數。首先,你得知道 memcpy 函數是幹什麼的吧。memcpy 函數是記憶體拷貝函數,函數原型為:
void * memcpy(void * dest, void * src, unsigned int n);
實作的功能是從源(src)記憶體位址的起始位置開始,拷貝 n 個位元組到目标(dest)記憶體位址。核心代碼很簡單,就是兩個指針之間的指派,然後同時向後移動。
*dest++ = *src++;
但是,我們需要注意兩點:
- 兩個指針可能不是同一資料類型,這樣就不能保證它們自增(++)時,往後移動的位元組數是一樣的,是以,需要先将它們強制轉換成 char *,再向後移動;
- 存在記憶體重疊的可能,如下圖,src 指向的資料存放在記憶體位址為 [10001,10101] 的範圍内,dest 指向的位址剛好落在這個範圍内,如果還是按上面的語句指派,會發生資料覆寫的情況。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5yY5EDO2cjMjNmN0ETYyQmNjZjZ3EGNkZTNzImNiJjMz8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
我們可以通過從後往前拷貝資料,解決記憶體重疊問題。最終代碼如下:
void * memcpy(void * dest, const void * src, unsigned int count){ if (NULL== dest || NULL == src || 0 == count) { return NULL; } char * d; const char * s; if (dest > (src + count) || dest < src) { d = (char *)dest; s = (char *)src; while (count--) { *d++ = *s++; } } else { d = (char *)(dest + count - 1); s = (char *)(src + count - 1); while (count--) { *d-- = *s--; } } return dest;}
每天一個開發小知識,今天你學廢了嗎?