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

首頁綜合 正文
目錄

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

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

http://yzkb.51969.com/

? ? ? ? Hi~!這里是奮斗的小羊,很榮幸各位能閱讀我的文章,誠請評論指點,歡迎歡迎~~? ? ?

?????????????????????????????????????????????????個人主頁:小羊在奮斗

?????????????????????????????????????????????????所屬專欄:C語言? ?

????????本系列文章為個人學習筆記,在這里撰寫成文一為鞏固知識,二為一些學友們展示一下我的學習過程及理解。文筆、排版拙劣,望見諒。?

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

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

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

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

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

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

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

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

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

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

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

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

? ? ? ? 這個函數(shù)還是比較簡單的。

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

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

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

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

#include

#include

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

{

assert(dest && sour);

void* pd = dest;

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

{

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

((char*)dest)++;

((char*)sour)++;

}

return pd;//返回目標空間的起始地址

}

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;

}

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

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

? ? ? ? 可以看到,當我們在一個內(nèi)存區(qū)域內(nèi)拷貝,并且內(nèi)存有重疊的時候,my_memcpy 函數(shù)就不能完成我們想要的結果了,這是因為重疊的部分已經(jīng)被拷貝過來的內(nèi)容代替,原內(nèi)容就消失了,當拷貝到重疊的內(nèi)存區(qū)域時,拷貝的還是之前拷貝過來的內(nèi)容。不過只要內(nèi)存不重疊,在一個內(nèi)存區(qū)域內(nèi)拷貝也是可行的。

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

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

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

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

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

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

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

#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;

}

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

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

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

? ? ? ? 讓我們再回到之前遇到的問題,如果內(nèi)存重疊時拷貝會將原內(nèi)容覆蓋。那是不是我們拷貝的方法有問題呢?來看:

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

?

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

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

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

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

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

? ? ? ? 那么,我們就可以在拷貝之前先比較一下指針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;

}

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

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

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

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

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

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

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

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

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

??

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

??????????如果覺得我的文章還不錯,請點贊、收藏 + 關注支持一下,我會持續(xù)更新更好的文章。??

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

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

http://yzkb.51969.com/

好文閱讀

評論可見,查看隱藏內(nèi)容

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

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

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

發(fā)布評論

您暫未設置收款碼

請在主題配置——文章設置里上傳

掃描二維碼手機訪問

文章目錄