本篇文章聊一下strcpy和memcpy的代碼實現,這兩個也是c和c++面試中常考的問題點。c++
首先看一下,一份標準的strcpy
的實現以下:面試
char *strcpy(char* strDest, const char* strSrc) { assert( (strDest != NULL) && (strSrc != NULL)); char *address = strDest; while((*strDest++ = *strSrc++) != '\0'); return address; }
這裏有以下幾點須要注意:函數
char*
,且返回了目標字符串指針的原值,使得函數能夠支持鏈式表達式,增長了函數的附加值。以上這些點不僅適用於strcpy這裏,而是咱們任什麼時候候寫代碼都儘可能遵循這些規則,這樣才能寫出高可用、高健壯性的代碼。this
對於以上代碼,咱們能夠看出來,它是存在隱患的,當源字符串的長度超出目標字符串時,會致使把數據寫入到咱們沒法控制的地址中去,存在很大的風險,因此就有了strncpy,下面也給一個strncpy的實現,以下:spa
char *strncpy(char* strDest, const char* strSrc, size_t n) { assert( (strDest != NULL) && (strSrc != NULL)); char *address = strDest; while ( n-- && (*strDest++ = *strSrc++) != '\0'); return address; }
要根據輸入的長度作一個控制,而每每咱們使用的時候,輸入的長度都是目標字符串的長度減1,由於要留一個位置給結束符'\0'
。指針
memcpy的實現其實能夠參考strncpy的實現,好比咱們把指針類型轉換成char*來實現拷貝,這種方式就是按照一個字節一個字節來進行拷貝了,首先仍是一睹代碼爲快,以下:code
#include <stdio.h> #include <string.h> struct people { int iAge; char szName[12]; char szSex[3]; }; //模擬memcpy的實現 void * mymemcpy(void *dest, const void *src, size_t n) { if (dest == NULL || src == NULL) return NULL; char *pDest = static_cast <char*>(dest); const char *pSrc = static_cast <const char*>(src); if (pDest > pSrc && pDest < pSrc+n) { for (size_t i=n-1; i != -1; --i) { pDest[i] = pSrc[i]; } } else { for (size_t i= 0; i < n; i++) { pDest[i] = pSrc[i]; } } return dest; } int main() { people stPeople1, stPeople2; memset((void*)&stPeople1, 0x00, sizeof(stPeople1)); memset((void*)&stPeople2, 0x00, sizeof(stPeople2)); stPeople1.iAge = 32; mymemcpy(stPeople1.szName, "li lei", sizeof(stPeople1.szName)); mymemcpy(stPeople1.szSex, "man", sizeof(stPeople1.szSex)); mymemcpy((void*)&stPeople2, (void*)&stPeople1, sizeof(stPeople2)); printf("this people age is %d, name is %s, sex is %s\n", stPeople2.iAge, stPeople2.szName, stPeople2.szSex); return 0; }
咱們看mymemcpy的實現,此時是一個字節的實現,但它與strncpy實現不能同樣,看一下memcpy實現的注意點:內存
char*
類型來操做;'\0'
來判斷拷貝的結束,由於它是對一整塊內存的拷貝,舉一個淺顯的例子,假設拷貝一個結構體,相似上面代碼,那麼它極可能拷貝到中間的某個地方就中止了,這個拷貝就至關於沒有完成;可是這個時候若是面試官問你,按照4個字節來拷貝,該怎麼實現呢?字符串
根據前面的邏輯,其實按照4個字節拷貝就是把指針類型轉換成int*來拷貝,不過有一點不一樣的是,若是按照4個字節來拷貝,就沒辦法去判斷內存重疊的狀況了,由於內存的基本單位是一個字節,4個字節是沒有辦法避免覆蓋狀況的,一個可用的4個字節拷貝代碼以下:string
void * mymemcpy(void *dest, const void *src, size_t n) { if (dest == NULL || src == NULL) return NULL; int *pDest = (int*)dest; int *pSrc = (int*)src; int iWordNum = n/4; int iSlice = n%4; while(iWordNum--) { *pDest++ = *pSrc++; } char* pcDest = (char*)pDest; char* pcSrc = (char*)pSrc; while(iSlice--) { *pcDest++ = *pcSrc++; } return dest; }
按照4個字節判斷,一個清晰的思路是知足4個字節的按照int類型去拷貝,不知足4個字節的就仍是按照char類型去拷貝。
好了,關於strcpy和memcpy的實現就介紹到這裏,若是個人創做對你有用的話,麻煩點個讚唄。