今天去面試,面試官出了一個關於memcpy的函數原型的實現的問題,本來這個問題是很簡單的,但是不知道當時怎麼腦子一抽竟然寫錯了,真是”累覺不愛”了.感覺這份工作算是泡湯了,算了事情發生了,錯過了也就錯過了.既然這樣就把這件事情記錄下來,給自己提個醒~
這個問題對於接觸過的朋友自然不難,問題在於給自己一個分析的方法,遇到類似的問題怎麼解決.
memcpy實現內存拷貝,根據這個問題,我們可以提取出下面幾點:
1.可以拷貝任何數據,數據類型不能受限
2.源數據不能被改變
通過上面兩點可以確定函數原型為void *memcpy(void *dest, const void *src),現在分析一下這些足夠了嗎?這個函數拷貝什麼時候結束,當時我就用了這個函數原型,由於是拷貝的任意數據,所以不能指定一個明確的結束標志,既然這樣那麼只有明確的指定拷貝的大小才可以.所以函數原型變成這樣void *memcpy(void *dest, void *src, size_t count);好吧,函數原型既然已經確認了,剩下的應該就是寫函數了,先等等,先別急著寫函數,實際上對於C語言的開發者來說,重要的不是函數功能的實現,重要的是函數出錯時的處理,如果你用的是Java或者C#大不了拋個異常出來,軟件崩潰一下,不會對其他造成任何影響;C這東西弄不好會把整個系統弄癱瘓,所謂”兵馬未動,糧草先行”,我麼還是先考慮考慮出錯的問題吧!我們根據函數原型來分析,
void *memcpy(void *dest, const void *src, size_t count);
1.空指針的問題,如果dest、src兩者或者兩者之一為NULL,那麼自然能沒得完了;
2.拷貝大小count為小於等於0的值,自然也是不正確的;
3.目標有沒有足夠的大小容納源數據,這個我們在函數內部似乎也無法進行保證,但是我們自己也要想到
4.內存地址有沒有重疊,這個我們暫時不考慮了。
有了上面的提示寫起來自然比較簡單了
#include <stdio.h>
void *memcpy(void *dest, const void *src, size_t count)
{
if (NULL == dest || NULL == src || count <= 0)
return NULL;
while (count--)
*dest++ = *src++;
return dest;
}
上面這段代碼在Linux中使用gcc編譯是沒錯的,但是會有警告,所以改成這樣:
#include <stdio.h>
void *memcpy(void *dest, const void *src, size_t count)
{
if (NULL == dest || NULL == src || count <= 0)
return NULL;
while (count--)
*(char *)dest++ = *(char *)src++;
return dest;
}
OK,也就這樣了,要是面試官再問起內存重疊的問題,你再和他侃侃.
我的面試算是泡湯了.
總結:不要著急慢慢來,根據需求推出原型,根據原型推斷問題,這算是個教訓吧!!!
補充
在這裡非常感謝博客園的求道於盲 這位好心的網友指出了我程序中的兩個錯誤
1.返回了一個
2.size_t
所以
希望別人注意
void *memcpy(void *dest, const void *src, int count)
{
void *ptr = dest;
if (NULL == dest || NULL == src || count <= 0)
return NULL;
while (count--)
*(char *)dest++ = *(char *)src++;
return ptr;
}