網(wǎng)站美化教程下載北京谷歌優(yōu)化
c語(yǔ)言系列
文章目錄
- c語(yǔ)言系列
- 一、memmove函數(shù)介紹
- 1.1、函數(shù)基本功能
- 1.2、函數(shù)參數(shù)
- 2.3、函數(shù)返回值
- 二、memmove的使用
- 2.1、拷貝字節(jié)不可大于目標(biāo)空間
- 2.2、同一空間拷貝
- 三、函數(shù)功能的模擬實(shí)現(xiàn)
- 3.1、函數(shù)參數(shù)及其返回值的設(shè)定
- 3.2、函數(shù)體實(shí)現(xiàn)
- 四、代碼實(shí)現(xiàn)
一、memmove函數(shù)介紹
下面為該函數(shù)基本功能的介紹
1.1、函數(shù)基本功能
memmove的功能是將source指針指向空間的前num個(gè)字節(jié),拷貝到detination指針指向的空間,不同于memcpy函數(shù)的是,memmove函數(shù)允許,兩個(gè)指針指向的空間有重合。
1.2、函數(shù)參數(shù)
第一個(gè)參數(shù):它是無(wú)類(lèi)型指針(void*),指向要拷貝的目標(biāo)地址,因此也稱(chēng)為目標(biāo)指針。
第二個(gè)參數(shù):它是const修飾的無(wú)類(lèi)型指針(void*),指向要拷貝的源地址,因此稱(chēng)為源指針。
注:const修飾指針類(lèi)型時(shí)在*之前修飾,代表該指針指向?qū)ο蟮膬?nèi)容不能被修改(地址里的內(nèi)容不能改);在 * 之后修飾,代表該指針指向的對(duì)象不能被修改(指針本身不能被修改)
第三個(gè)參數(shù):無(wú)符號(hào)整型,代表拷貝字節(jié)數(shù)(拷貝字節(jié)不可能為負(fù)數(shù))
2.3、函數(shù)返回值
無(wú)類(lèi)型指針(void*),函數(shù)運(yùn)行結(jié)束后返回拷貝后的目的地內(nèi)存塊的起始地址.
二、memmove的使用
memove的返回值及兩個(gè)參數(shù)的類(lèi)型均為void*這也就意味著它可以適應(yīng)絕大多數(shù)類(lèi)型。相信絕大多數(shù)人來(lái)學(xué)習(xí)這個(gè)函數(shù),都是因?yàn)榕龅搅薽emcpy解決不了的場(chǎng)景了,而memmove相比之memcpy最大的優(yōu)點(diǎn)就是在面對(duì)目的地內(nèi)存塊和源頭內(nèi)存塊重疊空間是,依然可以安全的進(jìn)行拷貝操作,當(dāng)然對(duì)于不重疊情況它依然是可以解決的。
下面我們來(lái)演示一下,拷貝中可能遇到的情景,以便我們接下來(lái)的模擬實(shí)現(xiàn),對(duì)下面的情況在模擬時(shí),我會(huì)再仔細(xì)分析的。
2.1、拷貝字節(jié)不可大于目標(biāo)空間
int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8 };int arr2[5] = { 0 };memmove(arr2, arr1, sizeof(arr1[0])*8);//sizeof(arr1[0])*8,代表拷貝八個(gè)數(shù)組元素的字節(jié)return 0;
}
當(dāng)拷貝空間大于目標(biāo)空間時(shí)程序崩潰。
2.2、同一空間拷貝
情況一:
拷貝源空間與目的空間不重合,代碼及執(zhí)行結(jié)果
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8 };memmove(arr+8, arr, sizeof(arr[0])*2);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}
畫(huà)圖分析:
將source指向空間的前兩個(gè)元素拷貝到detination指向的空間(detination指向空間不足沒(méi)有影響)。
情況二:
拷貝源空間與目標(biāo)空間存在重合空間,且source指向空間在前(這里要注意,我對(duì)數(shù)組首元素地址進(jìn)行加法操作(arr+1等)指針是向后走的,也就是說(shuō)后面指針大于前面)
代碼及其運(yùn)行結(jié)果:
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8 };memmove(arr+3, arr, sizeof(arr[0])*4);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}
畫(huà)圖分析:
情況三:
拷貝源空間與目標(biāo)空間存在重合空間,且detination指向空間在前
代碼及其運(yùn)行結(jié)果:
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8 };memmove(arr, arr+3, sizeof(arr[0])*4);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}
畫(huà)圖分析:
三、函數(shù)功能的模擬實(shí)現(xiàn)
在實(shí)現(xiàn)過(guò)程中我們對(duì)標(biāo)庫(kù)中的定義,以及需要具備的功能來(lái)模擬完成它。
3.1、函數(shù)參數(shù)及其返回值的設(shè)定
由于memmove函數(shù)本身就是內(nèi)存拷貝函數(shù),并沒(méi)有參數(shù)和返回類(lèi)型的限定,我們這里同庫(kù)中一樣即可。
3.2、函數(shù)體實(shí)現(xiàn)
在上面使用部分的講解中,我們幾乎將所有可能出現(xiàn)的情況都給大家展示出來(lái)了(異地空間拷貝同上),接下來(lái)我們只需實(shí)現(xiàn)一個(gè)可以滿足這些功能的函數(shù)體及可,其它細(xì)節(jié)問(wèn)題會(huì)在代碼部分講解。
情況一分析:
我用藍(lán)色代表源空間待拷貝資源,紅色代表目的空間
從前往后拷貝:
從后往前拷貝:
(進(jìn)入函數(shù)先把指針先后移動(dòng))
這種情況沒(méi)有涉及源空間,與目標(biāo)空間的重合問(wèn)題,所有是很簡(jiǎn)單的,無(wú)論是從前往后拷貝還是從后往前拷貝都是可以完成的。
情況二分析:
博主手殘畫(huà)的丑大家見(jiàn)諒!!!
從前向后拷貝,數(shù)據(jù)(4)就會(huì)蓋.
當(dāng)源指針指向空間與目標(biāo)空間重合且源指針在目標(biāo)指針前面時(shí)(source<detination),我們必須從后往前拷貝才不會(huì)發(fā)生數(shù)據(jù)覆蓋。
情況三分析:
數(shù)據(jù)覆蓋
當(dāng)源指針指向空間與目標(biāo)空間重合且目標(biāo)指針在源指針】前面時(shí)(detination<source),我們必須從前往后拷貝才不會(huì)發(fā)生數(shù)據(jù)覆蓋。
四、代碼實(shí)現(xiàn)
對(duì)于異地拷貝時(shí),無(wú)論是從前往后拷貝還是從后向前拷貝都是可以完成拷貝的。,。
void* my_memmove(void* destination, void* source, size_t num)
{assert(destination&&source);//判斷是否為空指針char* dest = (char*)destination;const char* src = (char*)source;if (destination < source)//對(duì)標(biāo)情況三{while (num--){*dest++ = *src++;}}else//對(duì)標(biāo)情況二{while (num--){*(dest + num)= *(src + num);}}return destination;
}
寫(xiě)代碼時(shí)才發(fā)現(xiàn)上面?zhèn)€第一個(gè)指針拼錯(cuò)了,但是不影響邏輯,大家見(jiàn)諒!!!
文章時(shí)我在復(fù)習(xí)時(shí)寫(xiě)的,如果哪有錯(cuò)誤可以私信我,萬(wàn)分感謝!