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