欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

目錄

柚子快報(bào)激活碼778899分享:開發(fā)語(yǔ)言 C語(yǔ)言(內(nèi)存函數(shù))

柚子快報(bào)激活碼778899分享:開發(fā)語(yǔ)言 C語(yǔ)言(內(nèi)存函數(shù))

http://yzkb.51969.com/

? ? ? ? Hi~!這里是奮斗的小羊,很榮幸各位能閱讀我的文章,誠(chéng)請(qǐng)?jiān)u論指點(diǎn),歡迎歡迎~~? ? ?

?????????????????????????????????????????????????個(gè)人主頁(yè):小羊在奮斗

?????????????????????????????????????????????????所屬專欄:C語(yǔ)言? ?

????????本系列文章為個(gè)人學(xué)習(xí)筆記,在這里撰寫成文一為鞏固知識(shí),二為一些學(xué)友們展示一下我的學(xué)習(xí)過(guò)程及理解。文筆、排版拙劣,望見(jiàn)諒。?

????????????????????????????????1、memcpy 的使用和模擬實(shí)現(xiàn)

????????????????????????????????2、memmove 的使用和模擬實(shí)現(xiàn)

????????????????????????????????3、memset 函數(shù)的使用

????????????????????????????????4、memcmp 函數(shù)的使用

1、memcpy 的使用和模擬實(shí)現(xiàn)

? ? ? ? 1.1 ?memcpy?函數(shù)的使用?

? ? ? ? memcpy 前面的 mem 指的是 memmory ,英文單詞“記憶”,在C語(yǔ)言中指的是內(nèi)存。后面要介紹的 memmove、memset 和 memcmp 都是如此。

? ? ? ? memcpy 是一個(gè)內(nèi)存拷貝函數(shù),其作用是將一個(gè)內(nèi)存區(qū)域內(nèi)指定的 count 個(gè)字節(jié)大小的內(nèi)容拷貝到目標(biāo)內(nèi)存空間內(nèi)。值得注意的是,雖然 memcpy 是一個(gè)內(nèi)存函數(shù),但其是定義在 頭文件內(nèi)的。

?????????上面關(guān)于 memcpy 函數(shù)的作用及其用法的描述還是很好理解的,這里再做一些說(shuō)明。

? ? ? ? (1)為了使 memcpy 函數(shù)可以實(shí)現(xiàn)對(duì)任意類型的內(nèi)容拷貝,其參數(shù)定義為了 void *類型的指針;

? ? ? ? (2)跟之前學(xué)過(guò)的字符串相關(guān)的函數(shù)一樣,memcpy 函數(shù)拷貝的目標(biāo)空間必須是可修改的,而被拷貝的內(nèi)存區(qū)域可用 const 修飾;

? ? ? ? (3)當(dāng) source 和 destination 有任何重疊的時(shí)候,復(fù)制的結(jié)果都是未定義的,也就是說(shuō)memcpy 函數(shù)不負(fù)責(zé)重疊內(nèi)存的拷貝。

? ? ? ? 這個(gè)函數(shù)還是比較簡(jiǎn)單的。

? ? ? ?1.2??memcpy?函數(shù)的模擬實(shí)現(xiàn)

? ? ? ? memcpy 函數(shù)和 strcpy 函數(shù)有相似的地方,所以其實(shí)現(xiàn)的邏輯也就應(yīng)該和 strcpy 函數(shù)的模擬實(shí)現(xiàn)類似。首先我們需要搞清楚,為了實(shí)現(xiàn)對(duì)任意類型的內(nèi)容拷貝,我們將 memcpy 函數(shù)的參數(shù)及其返回值都設(shè)定成了 void * 類型的指針,但是 void * 類型的指針有缺點(diǎn),不能直接進(jìn)行解引用,也不能對(duì)其進(jìn)行 +- 操作,那我們就要想一個(gè)辦法解決這個(gè)問(wèn)題。

? ? ? ? 其實(shí)這個(gè)問(wèn)題我們之前在模擬實(shí)現(xiàn) qsort 函數(shù)的時(shí)候就有了一個(gè)解決辦法,就是將其強(qiáng)轉(zhuǎn)為char * 類型的指針,因?yàn)?char * 類型的指針指向的對(duì)象大小是一個(gè)字節(jié),是所有類型中字節(jié)大小最小的,不管對(duì)象類型是多大字節(jié),只要一個(gè)字節(jié)一個(gè)字節(jié)地拷貝,就可以對(duì)實(shí)現(xiàn)對(duì)任意類型的內(nèi)容拷貝了。

? ? ? ? 那有了上面的思路,我們就能寫出下面的代碼:

#include

#include

void* my_memcpy(void* dest, const void* sour, size_t count)

{

assert(dest && sour);

void* pd = dest;

while (count--)//控制拷貝多少個(gè)字節(jié)

{

*(char*)dest = *(char*)sour;

((char*)dest)++;

((char*)sour)++;

}

return pd;//返回目標(biāo)空間的起始地址

}

void text1()

{

int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };

int arr2[20] = { 0 };

int* pi = my_memcpy(arr2, arr1 + 2, 20);

for (int i = 0; i < 5; i++)

{

printf("%d ", *(pi + i));

}

printf("\n");

}

void text2()

{

char str1[] = "abcdefghijklmnopqrstuvwxyz";

char str2[20] = { 0 };

char* ps = my_memcpy(str2, str1 + 5, 10);

printf("%s\n", ps);

}

int main()

{

text1();

text2();

return 0;

}

? ? ? ? 跟之前我們模擬實(shí)現(xiàn) qsort 函數(shù)相比,這就是張飛吃豆芽。?

? ? ? ? 上面我們是將一個(gè)內(nèi)存區(qū)域的內(nèi)容拷貝到另一個(gè)內(nèi)存區(qū)域,那能不能實(shí)現(xiàn)在一個(gè)內(nèi)存區(qū)域內(nèi)的拷貝呢?我們來(lái)試一下:

? ? ? ? 可以看到,當(dāng)我們?cè)谝粋€(gè)內(nèi)存區(qū)域內(nèi)拷貝,并且內(nèi)存有重疊的時(shí)候,my_memcpy 函數(shù)就不能完成我們想要的結(jié)果了,這是因?yàn)橹丿B的部分已經(jīng)被拷貝過(guò)來(lái)的內(nèi)容代替,原內(nèi)容就消失了,當(dāng)拷貝到重疊的內(nèi)存區(qū)域時(shí),拷貝的還是之前拷貝過(guò)來(lái)的內(nèi)容。不過(guò)只要內(nèi)存不重疊,在一個(gè)內(nèi)存區(qū)域內(nèi)拷貝也是可行的。

? ? ? ? 但是,我們可以看到 memcpy 函數(shù)并沒(méi)有這個(gè)問(wèn)題,那是我們模擬的函數(shù)有問(wèn)題嗎?其實(shí)不是的,memcpy 函數(shù)之所以沒(méi)有這個(gè)問(wèn)題,是因?yàn)樵谀承┫到y(tǒng)上,memcpy函數(shù)可能會(huì)檢測(cè)是否源內(nèi)存和目標(biāo)內(nèi)存有重疊,并采取一些措施以確保正確的結(jié)果。然而,這種行為是不可靠的,不同的編譯器或系統(tǒng)的實(shí)現(xiàn)方式可能會(huì)導(dǎo)致不同的結(jié)果。

?????????上面的情況和我們?cè)?字符、字符串函數(shù)?中介紹到的用 strcat 函數(shù)實(shí)現(xiàn)一個(gè)字符串自己拼接到自己末尾產(chǎn)生的問(wèn)題是類似的,同樣的 strcat 函數(shù)表面上雖然也沒(méi)有什么問(wèn)題,但是這種行為也是不可靠的。為了代碼的可移植性和安全性,最好還是使用memmove 函數(shù)來(lái)處理重疊內(nèi)存的情況。接下來(lái)我們就來(lái)介紹 memmove 函數(shù)。?

2、memmove 的使用和模擬實(shí)現(xiàn)

? ? ? ? 2.1 memmove?函數(shù)的使用

? ? ? ? 對(duì)比 memcpy 函數(shù),memmove 函數(shù)與之是及其相似的,特別的是 memmove 函數(shù)操作的對(duì)象是可以重疊的,正如它所描述的它會(huì)將內(nèi)容如同先復(fù)制到一個(gè)臨時(shí)數(shù)組中,這樣就解決了目標(biāo)內(nèi)存區(qū)域的內(nèi)容被覆蓋的問(wèn)題。?

? ? ? ? 2.1 memmove?函數(shù)的模擬實(shí)現(xiàn)?

? ? ? ? 那么了解了 memmove 函數(shù)的邏輯,模擬實(shí)現(xiàn)它也不是什么難事。我們只需要?jiǎng)?chuàng)建一個(gè)臨時(shí)數(shù)組過(guò)渡就行,于是就得到了下面的代碼:

#include

#include

void* my_memmove(void* dest, const void* sour, size_t count)

{

assert(dest && sour);

void* pd = dest;

int i = 0;

char arr[1000] = { 0 };

for (i = 0; i < count; i++)

{

arr[i] = *(char*)sour;

((char*)sour)++;

}

for (i = 0; i < count; i++)

{

*(char*)dest = arr[i];

((char*)dest)++;

}

return pd;

}

int main()

{

int i = 0;

int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };

int sz = sizeof(arr1) / sizeof(arr1[0]);

my_memmove(arr1 + 2, arr1, 20);

for (i = 0; i < sz; i++)

{

printf("%d ", arr1[i]);

}

return 0;

}

? ? ? ? 是不是很簡(jiǎn)單呢,這樣我們就實(shí)現(xiàn)了模擬 memmove 函數(shù)的功能。但是上面這種創(chuàng)建臨時(shí)字符數(shù)組的辦法有一點(diǎn)不足,因?yàn)槲覀儾⒉荒艽_定被拷貝的內(nèi)容有多大,所以只能模糊地創(chuàng)建一個(gè)比較大的數(shù)組,但是這個(gè)比較大是多大沒(méi)辦法知道,創(chuàng)建大了浪費(fèi),創(chuàng)建小了不夠,那有沒(méi)有什么辦法能解決這個(gè)問(wèn)題呢??

? ? ? ? 2.3 memmove 函數(shù)的模擬優(yōu)化

? ? ? ? 既然我們并不能確定要?jiǎng)?chuàng)建一個(gè)多大的臨時(shí)數(shù)組,那我們干脆放棄創(chuàng)建臨時(shí)數(shù)組的方法另辟奇徑。

? ? ? ? 讓我們?cè)倩氐街坝龅降膯?wèn)題,如果內(nèi)存重疊時(shí)拷貝會(huì)將原內(nèi)容覆蓋。那是不是我們拷貝的方法有問(wèn)題呢?來(lái)看:

? ? ? ? 將紅色方框內(nèi)的內(nèi)容拷貝到藍(lán)色方框內(nèi):

?

? ? ? ? 我們發(fā)現(xiàn),從前向后拷貝行不通,因?yàn)闀?huì)覆蓋掉還沒(méi)拷貝的內(nèi)容;但從后向前拷貝是可行的,并沒(méi)有出現(xiàn)還沒(méi)拷貝的內(nèi)容被覆蓋的情況。

? ? ? ? 將藍(lán)色方框內(nèi)的內(nèi)容拷貝到紅色方框內(nèi):

????????我們又發(fā)現(xiàn),從后向前行不通,但從前向后是可行的。

? ? ? ? 而之所以有時(shí)需要從前向后拷貝,有時(shí)需要從后向前拷貝,是取決于是將前面的內(nèi)容拷貝到后面,還是將后面的內(nèi)容拷貝到前面。

? ? ? ? 前面介紹數(shù)組的時(shí)候我們說(shuō)過(guò),數(shù)組元素隨著下標(biāo)的增大地址逐漸增大。也就是說(shuō),如果上面需要將紅色方框內(nèi)的內(nèi)容拷貝到藍(lán)色方框內(nèi),那么當(dāng)指針p1小于指針p2時(shí),需要從后向前拷貝;當(dāng)指針p1大于指針p2時(shí),需要從前向后拷貝。而當(dāng)兩個(gè)內(nèi)存區(qū)域沒(méi)有重疊時(shí),從前向后和從后向前都是可行的。

? ? ? ? 那么,我們就可以在拷貝之前先比較一下指針dest和指針sour的大小,然后再選擇是從前向后拷貝還是從后向前拷貝。

#include

#include

void* my_memmove(void* dest, const void* sour, size_t count)

{

void* pd = dest;

assert(dest && sour);

if (dest < sour)//從前向后

{

while (count--)

{

*(char*)dest = *(char*)sour;

((char*)dest)++;

((char*)sour)++;

}

}

else//從后向前

{

while (count--)

{

*((char*)dest + count) = *((char*)sour + count);

}

}

return pd;

}

void text1()

{

int i = 0;

int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };

int sz = sizeof(arr1) / sizeof(arr1[0]);

my_memmove(arr1 + 2, arr1, 20);

for (i = 0; i < sz; i++)

{

printf("%d ", arr1[i]);

}

}

void text2()

{

int i = 0;

int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };

int sz = sizeof(arr1) / sizeof(arr1[0]);

my_memmove(arr1, arr1 + 2, 20);

for (i = 0; i < sz; i++)

{

printf("%d ", arr1[i]);

}

}

void text3()

{

int i = 0;

char str1[] = "abcdefghijklmn";

int sz = sizeof(str1) / sizeof(str1[0]);

my_memmove(str1, str1 + 2, 5);

printf("%s\n", str1);

}

void text4()

{

int i = 0;

char str1[] = "abcdefghijklmn";

int sz = sizeof(str1) / sizeof(str1[0]);

my_memmove(str1 + 2, str1, 5);

printf("%s\n", str1);

}

int main()

{

//text1();

//text2();

//text3():

text4();

return 0;

}

? ? ? ? 這時(shí)候我們寫的 my_memmove 函數(shù)就比較完善了。

? ? ? ? 其實(shí)小伙伴們也能感覺(jué)到 memmove 函數(shù)完全可以代替 memcpy 函數(shù),而且 memmove 函數(shù)不用管內(nèi)存是否重疊的問(wèn)題。那 memcpy 函數(shù)不就沒(méi)有存在的必要了嗎?其實(shí)內(nèi)存重疊只是一種特殊情況,在確定沒(méi)有內(nèi)存重疊的情況下使用 memcpy 函數(shù)效率會(huì)更高,因?yàn)?memcpy 函數(shù)沒(méi)有比較指針大小這一步驟。

? ? ? ? 當(dāng)然如果你嫌麻煩始終使用 memmove 函數(shù)也是沒(méi)有什么問(wèn)題的,就是效率低那么一丟丟而已。

3、memset?函數(shù)的使用

? ? ? ? memset 函數(shù)是用來(lái)設(shè)置內(nèi)存的,它的作用是將內(nèi)存中的值以字節(jié)為單位設(shè)置成想要的內(nèi)容。?

? ? ? ? 需要注意的是,memset 函數(shù)是以字節(jié)為單位設(shè)置的,如果對(duì)這個(gè)規(guī)則模糊的話很容易寫出下面這種代碼:

? ? ? ? 我們知道整型占4個(gè)字節(jié),整數(shù)7以16進(jìn)制表示為:0x07?00 00 00,上面的代碼執(zhí)行過(guò)后就變成了:0x01 01 01 01,并沒(méi)有達(dá)到我們想要的效果。所以我們要謹(jǐn)記 memset 函數(shù)是以字節(jié)為單位一個(gè)字節(jié)一個(gè)字節(jié)設(shè)置的,并不是以元素為單位的。

4、memcmp?函數(shù)的使用

? ? ? ? memcmp 函數(shù)和 strncmp 函數(shù)極其相似,也是比較兩個(gè)指針指向內(nèi)容的大小,唯一的區(qū)別是 strncmp 只能比較字符串,而 memcmp 可以比較任意類型。和 memset 函數(shù)一樣 memcmp 也是以字節(jié)為單位比較的。?

??

? ? ? ? 以上所有的函數(shù)都是可以操作內(nèi)存的函數(shù),與前面介紹的字符、字符串函數(shù)不同的是內(nèi)存函數(shù)可以操作任意類型的內(nèi)容。?

??????????如果覺(jué)得我的文章還不錯(cuò),請(qǐng)點(diǎn)贊、收藏 + 關(guān)注支持一下,我會(huì)持續(xù)更新更好的文章。??

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 點(diǎn)擊跳轉(zhuǎn)下一節(jié) —>?C語(yǔ)言(數(shù)據(jù)存儲(chǔ))?

柚子快報(bào)激活碼778899分享:開發(fā)語(yǔ)言 C語(yǔ)言(內(nèi)存函數(shù))

http://yzkb.51969.com/

好文閱讀

評(píng)論可見(jiàn),查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19039630.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問(wèn)

文章目錄