目錄
作用:內(nèi)存拷貝
函數(shù)原型:
注意:count:要拷貝的字節(jié)數(shù)
函數(shù)memcpy從src位置開始向后賦值count個(gè)字節(jié)的數(shù)據(jù)到dest的內(nèi)存位置,
遇到 ‘/0’ 的時(shí)候不停下來
如果source和destination有任何的重疊,復(fù)制的結(jié)果都是未定義的
使用樣例:
int main(){ int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[20] = { 0 }; memcpy(arr2, arr1, sizeof(int) * 10); int i = 0; for (i = 0;i < 20; i++) { printf("%d ", arr2[i]); } return 0;}
模擬實(shí)現(xiàn):
void* my_memcpy(void* dest,const void* src,size_t count ){ assert(dest&&src); void* ret = dest; //為了返回目標(biāo)空間起始地址 //共拷貝n個(gè)字節(jié) while(count--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1;//這樣寫是防止編譯器報(bào)錯(cuò) src = (char*)src + 1; } //若寫成 dest = (char*)dest++; //有些編譯器可能跑不過去 return ret;}int main(){ int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[20] = { 0 }; my_memcpy(arr2, arr1, sizeof(int) * 10); int i = 0; for (i = 0;i < 10; i++) { printf("%d ", arr2[i]); } return 0;}
注意:我們這種模擬實(shí)現(xiàn)的方法,不能處理重疊的內(nèi)存拷貝,
如:想要將數(shù)組的1234拷貝到3456中,
void* my_memcpy(void* dest, const void* src, size_t count){ assert(dest && src); void* ret = dest; //為了返回目標(biāo)空間起始地址 //共拷貝n個(gè)字節(jié) while (count--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1;//這樣寫是防止編譯器報(bào)錯(cuò) src = (char*)src + 1; } //若寫成 dest = (char*)dest++; //有些編譯器可能跑不過去 return ret;}int main(){ int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; my_memcpy(arr+2, arr, 16); int i = 0; for (i = 0;i < 10; i++) { printf("%d ", arr[i]); } return 0;}
?想要的效果:1212347890
使用my_memcpy得到的結(jié)果:1 2 1 2 1 2 7 8 9 10
?
但是使用庫(kù)函數(shù)memcpy函數(shù),可以實(shí)現(xiàn)拷貝
但是C語言只要求memcpy函數(shù)可以實(shí)現(xiàn)不重疊的內(nèi)存拷貝即可,要實(shí)現(xiàn)重疊內(nèi)存拷貝的話,實(shí)現(xiàn)memmove函數(shù) ?
作用:內(nèi)存拷貝-可處理重疊的內(nèi)存拷貝
函數(shù)原型:
和memcpy的差別就是memmove函數(shù)處理的源內(nèi)存塊和目標(biāo)內(nèi)存塊是可以重疊的。
如果源空間和目標(biāo)空間出現(xiàn)重疊,就得使用memmove函數(shù)處理。
使用樣例:
int main(){ int arr[] ={1,2,3,4,5,6,7,8,9,10}; memmove(arr+2,arr,16); int i = 0; for(i = 0;i <10;i++) { printf("%d ",arr[i]); } return 0;}
打印結(jié)果:1 2 1 2 3 4 7 8 9 10
?模擬實(shí)現(xiàn):
以dest
注意:由于不知道傳過來的是什么類型的數(shù)據(jù),所以可以使用void*類型接收參數(shù)
返回目標(biāo)空間的起始地址
由于只知道拷貝的字節(jié)數(shù),不知道拷貝的類型->使用char*類型,每次拷貝一個(gè)字節(jié)
從前向后拷貝:dest和src強(qiáng)轉(zhuǎn)為char*類型,然后+1,共拷貝n次即可
如何從后向前拷貝
->原數(shù)據(jù)的最后拷貝到目標(biāo)位置的最后,然后二者不斷往前拷貝
從后往前拷貝:dest和src強(qiáng)轉(zhuǎn)為char*類型后,+count,跳過count個(gè)字節(jié),指向要拷貝的最后一個(gè)字節(jié),不斷拷貝,count--
?
?
void* my_memmove(void* dest, void* src, size_t count){ assert(dest && src); void* tmp = dest;//后序返回目標(biāo)空間的地址 if (dest < src) { //共拷貝count次 while (count--) { //從前往后拷貝 *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } } else { //從后往前拷貝 while (count--) { *((char*)dest + count) = *((char*)src + count); } } return tmp;}int main(){ int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; //my_memmove(arr+2,arr,16); my_memmove(arr , arr+2, 16); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr[i]); } return 0;}
作用:內(nèi)存比較
函數(shù)原型:
?
使用strcmp()只能比較字符串,而memcmp()可以比較整形,也可以比較字符串 ?
使用樣例:
int main(){ int arr1[] = {1,2,3,4}; //01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 int arr2[] = {1,2,3,5}; //01 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00 int ret = memcmp(arr1,arr2,12); //比較前12個(gè)字節(jié),二者相同,返回0 printf("%d/n",ret);//0 ret = memcmp(arr1,arr2,13); //比較前13個(gè)字節(jié),arr1中的04比arr2中的05小,返回-1 printf("%d/n",ret); //-1}
?模擬實(shí)現(xiàn)memcmp()
注意:由于不知道傳過來的是什么類型->使用void*類型接收,由于要比較的字節(jié)數(shù)恒大于0,所以用size_t接收,
由于只知道要比較的字節(jié)數(shù),不知道是什么類型->所以使用char* 一個(gè)字節(jié)一個(gè)字節(jié)的向后比較,直到找到二者中字節(jié)對(duì)應(yīng)內(nèi)容不相等時(shí),比較此時(shí)二者字節(jié)內(nèi)容
int my_memcmp(const void* p1, const void* p2, size_t count){ assert(p1 && p2); while (count--) { //如果二者指向的一個(gè)字節(jié)內(nèi)容相等->指向下一個(gè)字節(jié) if (*(char*) p1 == *(char*)p2) { p1 = (char*)p1+1; p2 = (char*)p2+1; } else { //此時(shí)二者指向的字節(jié)內(nèi)容不相同 //通過強(qiáng)轉(zhuǎn)為char* 比較此時(shí)二者指向的一個(gè)字節(jié)內(nèi)容 if ((*(char*)p1 - *(char*)p2) > 0) { return 1; } else { return -1; } } } //跳出循環(huán)時(shí),count = 0,說明二者要比較的字節(jié)的內(nèi)容都相同 return 0;}int main(){ int arr1[] = { 1,2,3,4 }; //01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 int arr2[] = { 1,2,3,99 }; //01 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00 int ret = my_memcmp(arr1, arr2, 12); //比較前12個(gè)字節(jié),二者相同,返回0 printf("%d/n", ret); //0 ret = my_memcmp(arr1, arr2, 13); //比較前13個(gè)字節(jié),arr1中的04比arr2中的05小,返回-1 printf("%d/n", ret); //-1 char* p1 = "Mangopp"; char* p2 = "Mangoppp"; ret = memcmp(p1, p2, 8); printf("%d/n", ret); //-1}
作用:內(nèi)存設(shè)置函數(shù)
函數(shù)原型:
?
將緩沖區(qū)設(shè)置為指定的字符
以字節(jié)為單位進(jìn)行初始化
-----------------
使用樣例:
int main(){ int arr[] = {1,2,3,4,5}; memset(arr,0,20); //初始化20個(gè)字節(jié)內(nèi)容為0 memset(arr,1,20); //初始化20個(gè)字節(jié)內(nèi)容為1 return 0;}
?
?
?
?
?注意點(diǎn):以字節(jié)為單位進(jìn)行初始化
?模擬實(shí)現(xiàn)
注意:由于不知道傳過來的是什么類型->使用void*類型接收,由于要設(shè)置的字節(jié)數(shù)恒大于0,所以用size_t接收,
由于只知道要設(shè)置的字節(jié)數(shù),不知道是什么類型->所以使用char* 一個(gè)字節(jié)一個(gè)字節(jié)的向后設(shè)置
返回目標(biāo)空間的起始地址
寫法1:接收類型為整形
memset:將緩沖區(qū)設(shè)置為指定的字符,所以要把整形強(qiáng)轉(zhuǎn)為字符型,再把每一個(gè)字節(jié)設(shè)置為整形對(duì)應(yīng)ascii的字符
void* my_memset(void* dest, int c, size_t count){ assert(dest); void* tmp = dest; char set_c = (char)c; //內(nèi)存設(shè)置,共設(shè)置count個(gè)字節(jié) while (count--) { *(char*)dest = set_c; dest = (char*)dest + 1; } return tmp;}int main(){ int arr[] = { 1,2,3,4,5 }; my_memset(arr, 0, 20); //初始化20個(gè)字節(jié)內(nèi)容為0 my_memset(arr, 1, 20);//初始化20個(gè)字節(jié)的內(nèi)容為1 return 0;}
?
寫法2:接收類型為字符
若直接設(shè)置字符,要設(shè)置的是其對(duì)應(yīng)的值 1 而不是其對(duì)應(yīng)的ascii碼值。所以要減去‘0’
‘1’ - ‘0’ -> 1 所以接收的字符還要減上字符0
void* my_memset(void* dest, char c, size_t count){ assert(dest); void* tmp = dest; //內(nèi)存設(shè)置,共設(shè)置count個(gè)字節(jié) while (count--) { *(char*)dest = c - "0"; dest = (char*)dest + 1; } return tmp;}int main(){ int arr[] = { 1,2,3,4,5 }; my_memset(arr, "0", 20); //初始化20個(gè)字節(jié)內(nèi)容為0 my_memset(arr, "1", 20); return 0;}
作用:可以返回C語言內(nèi)置的錯(cuò)誤碼對(duì)應(yīng)的錯(cuò)誤信息
函數(shù)原型:
返回錯(cuò)誤碼對(duì)應(yīng)的錯(cuò)誤信息
參數(shù)傳錯(cuò)誤碼,翻譯成錯(cuò)誤信息,返回的是錯(cuò)誤碼對(duì)應(yīng)的錯(cuò)誤信息的字符串的首字符地址
C語言庫(kù)函數(shù)調(diào)用失敗的時(shí)候,會(huì)把錯(cuò)誤碼存儲(chǔ)到errno變量中
?使用樣例:
#includeint main(){ printf("%s/n",strerror(0)); printf("%s/n",strerror(1)); printf("%s/n",strerror(2)); printf("%s/n",strerror(3)); return 0;}
打印結(jié)果:
No error
Operation not permitted
No such file or directory
No such process?
?應(yīng)用:
int main(){ FILE* pf = fopen("test.txt","r"); if(pf == NULL) { printf("%s/n",strerror(errno)); //C會(huì)把錯(cuò)誤碼放到errno變量,打印錯(cuò)誤碼對(duì)應(yīng)的錯(cuò)誤信息 } else { printf("打開成功/n"); } return 0;}//fopen():打開文件的函數(shù),如果打開成功,返回指向該文件的文件指針FILE* 如否則返回NULL//r:只讀方式打開
由于我們沒有此文件:所以打印結(jié)果
No such file or directory
作用:
函數(shù)原型:
?
string:自定義字符
使用樣例:
int main(){ FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { perror("測(cè)試"); perror("測(cè)試:/n"); perror("/n"); } else { printf("打開成功/n"); } return 0;}
?測(cè)試: No such file or directory
測(cè)試:
: No such file or directory
: No such file or directory
如果perror中有內(nèi)容,先打印內(nèi)容,然后自動(dòng)在后面加上冒號(hào): 然后打印錯(cuò)誤信息
缺點(diǎn):不想打印時(shí)也打印了
最后,感謝你能看到這里!如果感覺此文對(duì)你有所幫助的,歡迎留個(gè)三連呀!感謝
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/122566.html
摘要:本文介紹了類的常用接口的使用,并對(duì)其進(jìn)行了模擬實(shí)現(xiàn),對(duì)模擬實(shí)現(xiàn)中涉及到的深淺拷貝問題進(jìn)行了解析。在此之前,必須提到一個(gè)經(jīng)典問題。為了解決淺拷貝問題,所以中引入了深拷貝。但是實(shí)際使用中需要是第一個(gè)形參對(duì)象,才能正常使用。 本文介紹了string類的常用接口的使用,并對(duì)其進(jìn)行了模擬實(shí)現(xiàn),對(duì)模擬實(shí)...
摘要:自己實(shí)現(xiàn)時(shí)返回值可根據(jù)實(shí)際情況而定源字符串必須以結(jié)束。語言中給了一些長(zhǎng)度受限的字符串函數(shù),而前面的函數(shù)是長(zhǎng)度不受限的字符串函數(shù)。拷貝個(gè)字符從源字符串到目標(biāo)空間。 目錄 字符函數(shù)和字符串函數(shù) 函數(shù)介紹 strlen strcpy strcat strcmp strncpy ?strncat s...
摘要:本文介紹了的常用接口的使用,并對(duì)其進(jìn)行了模擬實(shí)現(xiàn),包括迭代器的實(shí)現(xiàn)。與為反向迭代器,對(duì)迭代器執(zhí)行操作,迭代器向前移動(dòng)。 本文介紹了list的常用接口的使用,并對(duì)其進(jìn)行了模擬實(shí)現(xiàn),包括list迭代器的實(shí)現(xiàn)。 目錄 一、list的介紹 二、list的常用接口的使用 1. list的構(gòu)造 2. l...
摘要:四函數(shù)字符串追加函數(shù)介紹函數(shù)的返回值類型為,可以返回被追加的字符串的起始地址。利用函數(shù)所需的頭文件函數(shù)的使用代碼運(yùn)行結(jié)果為函數(shù)的特點(diǎn)及注意事項(xiàng)源字符串必須以結(jié)束。目標(biāo)空間必須有足夠的大,能容納下源字符串的內(nèi)容。 ...
摘要:源字符串不修改,所以用修飾找到目標(biāo)空間的位置跳出循環(huán)時(shí),指向的就是目標(biāo)空間的位置,從該位置向后追加,相當(dāng)于作用字符串比較函數(shù),是比較字符串的庫(kù)函數(shù),比較的是字符串的內(nèi)容,不是長(zhǎng)度。 ?今天是2021年9月21日,首先祝大家中秋節(jié)快樂啦!但愿人長(zhǎng)久,千里共嬋娟。又是一年月圓,祝大家在中秋節(jié)都能...
閱讀 1417·2021-11-09 09:45
閱讀 1785·2021-11-04 16:09
閱讀 1449·2021-10-14 09:43
閱讀 1814·2021-09-22 15:24
閱讀 1589·2021-09-07 10:06
閱讀 1596·2019-08-30 14:15
閱讀 980·2019-08-30 12:56
閱讀 1563·2019-08-29 17:22