String底層函數(shù)的實(shí)現(xiàn)方式詳解
一、常見(jiàn)的String封裝函數(shù)
1. strcpy函數(shù)的實(shí)現(xiàn)
char *strcpy(char *dest, const char *src)
{
char *tmp = dest;
while ((*dest++ = *src++) != '\0')
/* nothing */;
return tmp;
}注意:strcpy 函數(shù)的返回值類(lèi)型為 char* ,即目標(biāo)字符串的起始地址,主要有以下兩個(gè)原因:
- 方便鏈?zhǔn)奖磉_(dá)式:通過(guò)返回目標(biāo)字符串的指針,可以方便地在連續(xù)的字符串操作函數(shù)中進(jìn)行鏈?zhǔn)秸{(diào)用。比如可以將
strcpy與其他字符串操作函數(shù)(如strcat)連續(xù)使用,如result = strcpy(dest, src1); result = strcat(result, src2);。這樣可以在一行代碼中完成多個(gè)字符串拷貝和連接的操作。 - 返回傳入的目標(biāo)指針:
strcpy函數(shù)在內(nèi)部會(huì)修改目標(biāo)字符串指針dest的值,使其指向復(fù)制后的字符串的結(jié)尾位置。通過(guò)返回目標(biāo)字符串的起始地址,可以方便地獲取復(fù)制后的字符串,并進(jìn)行后續(xù)的操作或驗(yàn)證。
2. strncpy函數(shù)的實(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ù)的實(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ù)的實(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ù)的實(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ù)的實(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ù)的實(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ù)的實(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ù)的實(shí)現(xiàn)
void *memset(void *s, int c, size_t count)
{
char *xs = s;
while (count--)
*xs++ = c;
return s;
}10. memcpy函數(shù)的實(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)存重疊問(wèn)題
memcpy函數(shù)將src的字節(jié)數(shù)復(fù)制到dest。如果源和目標(biāo)重疊,這個(gè)函數(shù)不能確保重疊區(qū)域的原始源字節(jié)在被覆蓋之前被復(fù)制。
一. 高地址向低地址進(jìn)行拷貝由于在虛擬地址空間中,??臻g的生長(zhǎng)方向是高地址向低地址生長(zhǎng),首先采用這種方式。簡(jiǎn)略的講就是源字符串中的字符從前往后向目標(biāo)字符串按給定字節(jié)的大小依此進(jìn)行拷貝。觀察上圖,可以得到兩個(gè)合理的區(qū)間即不會(huì)出現(xiàn)內(nèi)存覆蓋的區(qū)間。
(1)dest<=src
第一種情況dest=src,此時(shí)源字符串與目標(biāo)字符串指針指向同一個(gè)位置,拷貝的過(guò)程相當(dāng)自己給自己賦值,因此拷貝結(jié)束 后源字符串并沒(méi)有發(fā)生變化。
第二種情況dest < src,這樣的拷貝盡管會(huì)覆蓋src的內(nèi)容,出現(xiàn)了內(nèi)存重疊,但其可以完成內(nèi)存拷貝的功能,并沒(méi)有將錯(cuò)誤的信息拷貝過(guò)來(lái)。
(2)dest>=src+n當(dāng)dest>=src+n,無(wú)論如何都不會(huì)出現(xiàn)內(nèi)存重疊的問(wèn)題。
二. 低地址向高地址拷貝
(3)src<dest<src+n (內(nèi)存重疊)為了避免出現(xiàn)這種情況,我們可以將src和dest都移動(dòng) n-1個(gè)位置,這樣我們就可以從地址值向高地址進(jìn)行拷貝,這樣盡管也有可能目標(biāo)字符串覆蓋源字符串的情況,但是定影可以得到一個(gè)正確的拷貝。
- memove可以避免內(nèi)存拷貝時(shí)的重疊問(wèn)題。
- 實(shí)際上,memcpy只是memmove的一個(gè)子集。
- 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ù)的實(shí)現(xiàn)方式的文章就介紹到這了,更多相關(guān)String底層函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ 字符串string和整數(shù)int的互相轉(zhuǎn)化操作
這篇文章主要介紹了C++ 字符串string和整數(shù)int的互相轉(zhuǎn)化操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
C++實(shí)現(xiàn)LeetCode(147.鏈表插入排序)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(147.鏈表插入排序),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C語(yǔ)言超詳細(xì)講解雙向帶頭循環(huán)鏈表
帶頭雙向循環(huán)鏈表:結(jié)構(gòu)最復(fù)雜,一般用在單獨(dú)存儲(chǔ)數(shù)據(jù)。實(shí)際中使用的鏈表數(shù)據(jù)結(jié)構(gòu),都是帶頭雙向循環(huán)鏈表。另外這個(gè)結(jié)構(gòu)雖然結(jié)構(gòu)復(fù)雜,但是使用代碼實(shí)現(xiàn)以后會(huì)發(fā)現(xiàn)結(jié)構(gòu)會(huì)帶來(lái)很多優(yōu)勢(shì),實(shí)現(xiàn)反而簡(jiǎn)單2023-02-02
C語(yǔ)言?智能指針?shared_ptr?和?weak_ptr
這篇文章主要介紹了C語(yǔ)言?智能指針?shared_ptr?和?weak_ptr,weak_ptr引入可以解決shared_ptr交叉引用時(shí)無(wú)法釋放資源的問(wèn)題,下面來(lái)學(xué)習(xí)具體相關(guān)內(nèi)容吧,需要的朋友可以參考一下2022-04-04
C語(yǔ)言實(shí)現(xiàn)學(xué)生成績(jī)等級(jí)劃分的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言實(shí)現(xiàn)學(xué)生成績(jī)等級(jí)劃分的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
C語(yǔ)言安全編碼之?dāng)?shù)值中的sizeof操作符
這篇文章主要介紹了C語(yǔ)言安全編碼的數(shù)值中的sizeof操作符用法注意事項(xiàng),需要的朋友可以參考下2014-07-07

