String底層函數(shù)的實現(xiàn)方式詳解
一、常見的String封裝函數(shù)
1. strcpy函數(shù)的實現(xiàn)
char *strcpy(char *dest, const char *src) { char *tmp = dest; while ((*dest++ = *src++) != '\0') /* nothing */; return tmp; }
注意:strcpy
函數(shù)的返回值類型為 char*
,即目標字符串的起始地址,主要有以下兩個原因:
- 方便鏈式表達式:通過返回目標字符串的指針,可以方便地在連續(xù)的字符串操作函數(shù)中進行鏈式調(diào)用。比如可以將
strcpy
與其他字符串操作函數(shù)(如strcat
)連續(xù)使用,如result = strcpy(dest, src1); result = strcat(result, src2);
。這樣可以在一行代碼中完成多個字符串拷貝和連接的操作。 - 返回傳入的目標指針:
strcpy
函數(shù)在內(nèi)部會修改目標字符串指針dest
的值,使其指向復(fù)制后的字符串的結(jié)尾位置。通過返回目標字符串的起始地址,可以方便地獲取復(fù)制后的字符串,并進行后續(xù)的操作或驗證。
2. strncpy函數(shù)的實現(xiàn)
char *strncpy(char *dest, const char *src, size_t count) { char *tmp = dest; while (count) { if ((*tmp = *src) != 0) src++; tmp++; count--; } return dest; }
3. strcat函數(shù)的實現(xiàn)
char *strcat(char *dest, const char *src) { char *tmp = dest; while (*dest) dest++; while ((*dest++ = *src++) != '\0') ; return tmp; }
4. strncat函數(shù)的實現(xiàn)
char *strncat(char *dest, const char *src, size_t count) { char *tmp = dest; if (count) { while (*dest) dest++; while ((*dest++ = *src++) != 0) { if (--count == 0) { *dest = '\0'; break; } } } return tmp; }
5. strcmp函數(shù)的實現(xiàn)
int strcmp(const char *cs, const char *ct) { unsigned char c1, c2; while (1) { c1 = *cs++; c2 = *ct++; if (c1 != c2) return c1 < c2 ? -1 : 1; if (!c1) break; } return 0; }
6. strncmp函數(shù)的實現(xiàn)
int strncmp(const char *cs, const char *ct, size_t count) { unsigned char c1, c2; while (count) { c1 = *cs++; c2 = *ct++; if (c1 != c2) return c1 < c2 ? -1 : 1; if (!c1) break; count--; } return 0; }
7. strlen函數(shù)的實現(xiàn)
size_t strlen(const char *s) { const char *sc; for (sc = s; *sc != '\0'; ++sc) /* nothing */; return sc - s; }
8. strnlen函數(shù)的實現(xiàn)
size_t strnlen(const char *s, size_t count) { const char *sc; for (sc = s; count-- && *sc != '\0'; ++sc) /* nothing */; return sc - s; }
9. memset函數(shù)的實現(xiàn)
void *memset(void *s, int c, size_t count) { char *xs = s; while (count--) *xs++ = c; return s; }
10. memcpy函數(shù)的實現(xiàn)
void *memcpy(void *dest, const void *src, size_t count) { char *tmp = dest; const char *s = src; while (count--) *tmp++ = *s++; return dest; }
二、內(nèi)存重疊問題
memcpy函數(shù)將src的字節(jié)數(shù)復(fù)制到dest。如果源和目標重疊,這個函數(shù)不能確保重疊區(qū)域的原始源字節(jié)在被覆蓋之前被復(fù)制。
一. 高地址向低地址進行拷貝由于在虛擬地址空間中,??臻g的生長方向是高地址向低地址生長,首先采用這種方式。簡略的講就是源字符串中的字符從前往后向目標字符串按給定字節(jié)的大小依此進行拷貝。觀察上圖,可以得到兩個合理的區(qū)間即不會出現(xiàn)內(nèi)存覆蓋的區(qū)間。
(1)dest<=src
第一種情況dest=src,此時源字符串與目標字符串指針指向同一個位置,拷貝的過程相當自己給自己賦值,因此拷貝結(jié)束 后源字符串并沒有發(fā)生變化。
第二種情況dest < src,這樣的拷貝盡管會覆蓋src的內(nèi)容,出現(xiàn)了內(nèi)存重疊,但其可以完成內(nèi)存拷貝的功能,并沒有將錯誤的信息拷貝過來。
(2)dest>=src+n當dest>=src+n,無論如何都不會出現(xiàn)內(nèi)存重疊的問題。
二. 低地址向高地址拷貝
(3)src<dest<src+n (內(nèi)存重疊)為了避免出現(xiàn)這種情況,我們可以將src和dest都移動 n-1個位置,這樣我們就可以從地址值向高地址進行拷貝,這樣盡管也有可能目標字符串覆蓋源字符串的情況,但是定影可以得到一個正確的拷貝。
- memove可以避免內(nèi)存拷貝時的重疊問題。
- 實際上,memcpy只是memmove的一個子集。
- memcpy比memmove的速度要快一些。
void *memmove(void *dest, const void *src, size_t count) { char *tmp; const char *s; if (dest <= src) { tmp = dest; s = src; while (count--) *tmp++ = *s++; } else { tmp = dest; tmp += count; s = src; s += count; while (count--) *--tmp = *--s; } return dest; }
到此這篇關(guān)于String底層函數(shù)的實現(xiàn)方式的文章就介紹到這了,更多相關(guān)String底層函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ 字符串string和整數(shù)int的互相轉(zhuǎn)化操作
這篇文章主要介紹了C++ 字符串string和整數(shù)int的互相轉(zhuǎn)化操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12C++實現(xiàn)LeetCode(147.鏈表插入排序)
這篇文章主要介紹了C++實現(xiàn)LeetCode(147.鏈表插入排序),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07C語言?智能指針?shared_ptr?和?weak_ptr
這篇文章主要介紹了C語言?智能指針?shared_ptr?和?weak_ptr,weak_ptr引入可以解決shared_ptr交叉引用時無法釋放資源的問題,下面來學(xué)習(xí)具體相關(guān)內(nèi)容吧,需要的朋友可以參考一下2022-04-04