C語言內(nèi)存函數(shù)的實(shí)現(xiàn)示例
1.memcpy使用和模擬實(shí)現(xiàn)
mem -- memory在應(yīng)用中是記憶的意思,在計(jì)算機(jī)中是內(nèi)存的意思
1.1 memcpy的使用:
void * memcpy ( void * destination, const void * source, size_t num );
參數(shù)和返回值的類型是void*的指針是因?yàn)槿魏晤愋偷臄?shù)據(jù)都有可能拷貝,所以不能寫死,void*的指針可以接收任何類型的地址。
- 函數(shù)memcpy從source的位置開始向后復(fù)制num個(gè)字節(jié)的數(shù)據(jù)到destination指向的內(nèi)存位置。
- 這個(gè)函數(shù)在遇到'\0'的時(shí)候并不會(huì)停下來。
- 如果source和destination有任何的重疊,復(fù)制的結(jié)果都是未定義的。
#include <stdio.h> #include <string.h> int main() { int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[20] = { 0 }; memcpy(arr2, arr1 + 2, 20);//后面的20是字節(jié)個(gè)數(shù),一個(gè)整型四個(gè)字節(jié) for (int i = 0; i < 20; i++) { printf("%d ", arr2[i]); } return 0; }
注意:目標(biāo)空間必須可修改,目標(biāo)空間必須足夠大。
1.2 memcpy的模擬實(shí)現(xiàn):
#include <stdio.h> #include <assert.h> void* my_memcpy(void* dest, const void* src, size_t num) { void* ret = dest; assert(dest && src); //void* 的指針不能進(jìn)行直接運(yùn)算 void* 的指針是無具體類型的指針 for (int i = 0; i < num; i++) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; /* (char*)dest++; //強(qiáng)轉(zhuǎn)是臨時(shí)的,加加的時(shí)候也是無具體類型的 (char*)src++; //這種寫法不能保證在所有編譯器上都保證可行 ++(char*)dest;//這種在c++中編不過去,因?yàn)镃++中強(qiáng)制類型轉(zhuǎn)換的結(jié)果是臨時(shí)的 ++(char*)src;//臨時(shí)的變量是不能++的 */ } return ret; } int main() { int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[20] = { 0 }; my_memcpy(arr2, arr1 + 2, 20);//后面的20是字節(jié)個(gè)數(shù),一個(gè)整型四個(gè)字節(jié) for (int i = 0; i < 20; i++) { printf("%d ", arr2[i]); } return 0; }
將arr1中的12345拷貝放到arr1中的34567的位置。
int main() { int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 }; my_memcpy(arr1+2, arr1, 20);//后面的20是字節(jié)個(gè)數(shù),一個(gè)整型四個(gè)字節(jié) for (int i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; }
那么這里為什么會(huì)有問題呢?
所有當(dāng)我們時(shí)候自己寫的my_memcpy拷貝數(shù)據(jù)的時(shí)候當(dāng)我拷貝的這兩個(gè)空間是重疊的時(shí)候,就會(huì)出錯(cuò),所有memcpy不負(fù)責(zé)這種重疊內(nèi)存的拷貝,非要使用結(jié)果是未定義的,C語言標(biāo)準(zhǔn)沒有定義這個(gè)。
對(duì)于重疊的內(nèi)存,交給memmove來處理。
2. memmove 使用和模擬實(shí)現(xiàn)
2.1 memmove的使用:
void * memmove ( void * destination, const void * source, size_t num );
和memcpy的差別就是memmove函數(shù)的處理的源內(nèi)存塊和目標(biāo)內(nèi)存塊是可以重疊的。
如果源空間和目標(biāo)空間重疊,就得使用memmove函數(shù)處理。
#include <stdio.h> #include <string.h> int main() { int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 }; memmove(arr1+2, arr1, 20);//后面的20是字節(jié)個(gè)數(shù),一個(gè)整型四個(gè)字節(jié) for (int i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; }
2.2 memmove的模擬實(shí)現(xiàn):
#include <stdio.h> #include <assert.h> void* my_memmove(void* dest, const void* src, size_t num) { void* ret = dest; assert(dest && src); if (dest < src) { while (num--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } } else { while (num--) { *((char*)dest + num) = *((char*)src + num); } } return ret; } int main() { int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 }; my_memmove(arr1+2, arr1, 20);//后面的20是字節(jié)個(gè)數(shù),一個(gè)整型四個(gè)字節(jié) for (int i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; }
其實(shí)我們庫中的memcpy函數(shù)也能實(shí)現(xiàn)重疊拷貝。
這是因?yàn)镃語言規(guī)定memcpy只要能實(shí)現(xiàn)不重疊的拷貝就行,重疊的拷貝交給memmove。
我們發(fā)現(xiàn)vs上的庫函數(shù)memcpy函數(shù)也能實(shí)現(xiàn)重疊內(nèi)存的拷貝,但是不能保證別的編譯器也能實(shí)現(xiàn)。
3. memset函數(shù)的使用
void * memset ( void * ptr, int value, size_t num );
#include <stdio.h> #include <string.h> int main() { char arr[] = "hello world";//把hello world中的world改x memset(arr + 6, 'x', 5); printf("%s\n", arr); return 0; }
前面的數(shù)組是char類型,那么int類型的數(shù)組應(yīng)該如何使用memset呢?
#include <stdio.h> #include <string.h> int main() { int arr[10] = { 0 }; //memset(arr, 1, 4); //不能這樣寫,因?yàn)樽詈笠粋€(gè)參數(shù)的單位是字節(jié) //被改之后就是0x01 0x01 0x01 0x01,轉(zhuǎn)換成10進(jìn)制就是16843009,這是不對(duì)的 //所有把數(shù)組中的每個(gè)元素設(shè)置成1是做不到的,因?yàn)樗前醋止?jié)設(shè)置的,一個(gè)元素 //就占4個(gè)字節(jié) //借助for循環(huán)可以實(shí)現(xiàn) for (int i = 0; i < 4; i++) { memset(arr + i, 1, 1); } for (int i = 0; i < 10; i++) { printf("%d ", arr[i]); } return 0; }
4. memcmp函數(shù)的使用
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
#include <stdio.h> #include <string.h> int main() { int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 1,2,3,6,5 }; int ret = memcmp(arr1, arr2, 12);//比較前三個(gè),一個(gè)整型四個(gè)字節(jié),12個(gè)字節(jié) printf("%d\n", ret); return 0; }
前12個(gè)字節(jié)相等,所有返回0。
前13個(gè)字節(jié),arr1比arr2小,所以返回-1。
memcmp對(duì)于什么類型都可以比較。
到此這篇關(guān)于C語言內(nèi)存函數(shù)的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)C語言內(nèi)存函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C語言的字符串函數(shù),內(nèi)存函數(shù)筆記詳解
- c語言重要的字符串與內(nèi)存函數(shù)
- C語言內(nèi)存函數(shù)的使用及其模擬實(shí)現(xiàn)
- C語言詳解如何應(yīng)用模擬字符串和內(nèi)存函數(shù)
- C語言超詳細(xì)講解字符串函數(shù)和內(nèi)存函數(shù)
- C語言深入詳解四大內(nèi)存函數(shù)的使用
- C語言字符串函數(shù),字符函數(shù),內(nèi)存函數(shù)使用及模擬實(shí)現(xiàn)
- 深入了解C語言中的字符串和內(nèi)存函數(shù)
- 深度解析三個(gè)常見的C語言內(nèi)存函數(shù)
- C語言內(nèi)存函數(shù)的具體使用
- C語言實(shí)現(xiàn)內(nèi)存函數(shù)的示例代碼
相關(guān)文章
C++ main函數(shù)的幾點(diǎn)細(xì)節(jié)
這篇文章主要介紹了C++ main函數(shù)的幾點(diǎn)細(xì)節(jié),幫助大家更好的理解和學(xué)習(xí)C++,感興趣的朋友可以了解下2020-08-08C/C++ 中sizeof(''a'')對(duì)比詳細(xì)介紹
這篇文章主要介紹了C/C++ 中sizeof('a')的值對(duì)比詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2017-02-02C++實(shí)現(xiàn)拓?fù)渑判颍ˋOV網(wǎng)絡(luò))
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)拓?fù)渑判颍闹惺纠a介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04OpenMP task construct 實(shí)現(xiàn)原理及源碼示例解析
這篇文章主要為大家介紹了OpenMP task construct 實(shí)現(xiàn)原理及源碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03C++構(gòu)造函數(shù)初始化列表的實(shí)現(xiàn)詳解
構(gòu)造函數(shù)主要作用在于創(chuàng)建對(duì)象時(shí)為對(duì)象的成員屬性賦值,構(gòu)造函數(shù)由編譯器自動(dòng)調(diào)用,無須手動(dòng)調(diào)用;析構(gòu)函數(shù)主要作用在于對(duì)象銷毀前系統(tǒng)自動(dòng)調(diào)用,執(zhí)行一 些清理工作2022-09-09