Strcpy函數
1.strcpy聲明
char * strcpy( char * dest, const char * src );
功能:把 src 所指由NULL結束的字元串複制到 dest 所指的數組中。
說明:src 和 dest 所指記憶體區域不可以重疊且 dest 必須有足夠的空間來容納 src 的字元串。傳回指向 dest 結尾處字元(NULL)的指針。
2. strcpy的實作:
實作要求:
1,檢查指針有效性;
2,傳回目的指針ret;
3,源字元串的末尾 ‘\0’ 需要拷貝。
4, 考慮記憶體重疊情況
char *my_strcpy(char *dst,const char *src)
{
assert(dst != NULL);
assert(src != NULL);
char *ret = dst;
memcpy(dst,src,strlen(src)+);
return ret;
}
由于這裡的實作基于memcpy函數,下面我們也介紹memcpy函數的實作。
錯誤例子:(未考慮記憶體重疊現象)
char *my_strcpy(char *dst,const char *src)
{
assert(dst != NULL);
assert(src != NULL);
char *ret = dst;
while((* dst++ = * src++) != '\0')
;
return ret;
}
memcpy函數
1.memcpy函數的聲明
函數原型: void *memcpy(void*dest, const void *src, size_t n);
功能:從源src所指的記憶體位址的起始位置開始,拷貝n個位元組的資料到目标dest所指的記憶體位址的起始位置中。
說明:
1)src和dest所指記憶體區域不能重疊,函數傳回指向dest的指針。如果src和dest以任何形式出現了重疊,它的結果是未定義的。
2)與strcpy相比,memcpy遇到’\0’不結束,而且一定會複制完n個位元組。隻要保證src開始有n位元組的有效資料,dest開始有n位元組記憶體空間就行。
3)如果目标數組本身已有資料,執行memcpy之後,将覆寫原有資料(最多覆寫n個)。 如果要追加資料,則每次執行memcpy()後,要将目标位址增加到要追加資料的位址。
4)source和destin都不一定是數組,任意的可讀寫的空間均可.
2.memcpy函數的實作
這裡我們memcpy函數實作時考慮到了記憶體重疊的情況,可以完成指定大小的記憶體拷貝,memcpy的實作:
void * my_memcpy(void *dst,const void *src,unsigned int count)
{
assert(dst);
assert(src);
void * ret = dst;
if (dst <= src || (char *)dst >= ((char *)src + count))//源位址和目的位址不重疊,低位元組向高位元組拷貝
{
while(count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + ;
src = (char *)src + ;
}
}
else //源位址和目的位址重疊,高位元組向低位元組拷貝
{
dst = (char *)dst + count - ;
src = (char *)src + count - ;
while(count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst - ;
src = (char *)src - ;
}
}
return ret;
}
兩種不會出現記憶體重疊的圖形化解釋:
1,dst <= src
2, (char *)dst >= ((char *)src + count)
3. memcpy函數的優化(參見部落格:http://blog.csdn.net/xiaobo620/article/details/7488827)
改進思想:
大部分認為memcpy是一個char到char的拷貝的循環,擔心它的效率。實際上,memcpy是一個效率最高的記憶體拷貝函數,他不會那麼傻,來做一個一個位元組的記憶體拷貝,在位址不對齊的情況下,他是一個位元組一個位元組的拷,位址對齊以後,就會使用CPU字長來拷(和dma類似),32bit或64bit,還會根據cpu的類型來選擇一些優化的指令來進行拷貝。總的來說,memcpy的實作是和CPU類型、作業系統、cLib相關的。毫無疑問,它是記憶體拷貝裡效率最高的,請放心使用。(這是我從連結中的部落格拷貝過來的,請看原部落格,尊重原著)
void *mymemcpy(void *dst,const void *src,size_t num)
{
assert((dst!=NULL)&&(src!=NULL));
int wordnum = num/;//計算有多少個32位,按4位元組拷貝
int slice = num%;//剩餘的按位元組拷貝
int * pintsrc = (int *)src;
int * pintdst = (int *)dst;
while(wordnum--)*pintdst++ = *pintsrc++;
while (slice--)*((char *)pintdst++) =*((char *)pintsrc++);
return dst;
}
參考部落格:http://blog.csdn.net/gpengtao/article/details/7464061/
圖檔位址:https://www.processon.com/diagraming/595e38b7e4b0c2773f85b5e1
strncpy函數
1. strncpy函數的聲明
char * strncpy( char * dest, const char * src, size_t num );
功能:将字元串src中最多n個字元複制到字元數組dest中(它并不像strcpy一樣隻有遇到NULL才停止複制,而是多了一個條件停止,就是說如果複制到第n個字元還未遇到NULL,也一樣停止),傳回指向dest的指針。
2. strncpy函數的實作
/*
1.當要拷貝的字元個數(size_t n)小于或等于Src長度, Dest的最後不會加\0
2.當要拷貝的字元個數(size_t n)大于Src長度,Dest最後會自動追加一個\0
*/
char *mystrncpy(char *dest,const char *src,int n)
{
char *strDest=dest;
assert((dest!=NULL)&&(src!=NULL));
while( n &&(*dest++=*src++)!='\0')
{
n--;
}
if (n)
{
while(--n)
{
*dest++='\0';
}
}
return strDest;
}
2種不同情況的圖形化解釋:
1.
2.
參考部落格:http://blog.csdn.net/hgj125073/article/details/8464375
圖檔位址:https://www.processon.com/diagraming/595e3fbae4b0c5e101f306fa