記憶體操作函式
阿新 • • 發佈:2021-05-22
文章目錄
一.記憶體操作函式
記憶體操作函式適用於任何型別,但是它是以位元組為單位的。
1.memset函式
- 表現形式
適用於任何型別可以從void *看出。
- 作用
將ptr從第一個開始的num個位元組賦值為value。
#include<stdio.h>
#include<string.h>
int main(){
int arr[10] = { 0 };
memset(arr, 1, sizeof(arr));//按位元組為單位走 數字中的每一位為
printf("%x\n", arr[0]);//0000 0001 0000 0001 0000 0001 0000 0001
return 0;
}
輸出:
上面程式碼可以證明mem記憶體函式是以位元組為單位的。
2.memcpy函式
- 表現形式
引數為地址。
- 作用
將source按num個位元組拷貝到destination中。
注意:這個函式遇到’\0’並不會停下來,因為是記憶體操作。
但source與destination有重疊的,拷貝得不到想要的結果,函式不起效的,原因在模擬實現中說明。
#include<stdio.h>
#include<string.h>
struct stu{
char name[20];
int age;
};
int main(){
struct stu s1;
char a[] = "Jimer";
char *p = memcpy(s1.name, a, strlen(a) +1);//strlen加1是為了將'\0'拷貝進去。
printf("%s\n", s1.name);
printf("%s\n", p);
return 0;
}
輸出:
3.memmove函式
- 表現形式
與memcpy相同。 - 作用
也與memcpy相同,但是如果source與destination空間有重疊的地方,這個函式是起效的,可以得到想要的結果。
二.memcpy和memmove的模擬實現
上面說到,memcpy記憶體重疊時時不起效的,而memmove時起效的入下程式碼。
#include<stdio.h>
#include<string.h>
int main(){
char buff[] = "abcdefrt";
memcpy(buff+1, buff, strlen(buff) + 1);
memmove(buff+1, buff, strlen(buff) + 1);
return 0;
}
輸出:
memcpy使buff變成了“aaaaaaaa”。
memmove函式使得 buff變成了“aabcdefrt”。
但是由於編譯器已經將這一情況修正,所以輸出仍然會得到想要的結果。但是我們要知道這種情況。
為什麼會出現這種情況呢:
當第一個替換第二個時,第二個變成了a,第二個替換第三個時,第三個變成了a,如此。memcpy輸出為全a,但是memmove出現這種情況時是從後往前拷貝的,這樣就不會出現這種情況了。
memcpy模擬實現
#include<stdio.h>
#include<assert.h>
void *Mymemcpy(void* des, void* src, size_t size){
assert(des);//判斷des,src不為NULL。
assert(src);
char *_des = (char *)des;//按位元組為單位強轉成char *
char *_src = (char *)src;
while (size--){
*_des=*_src;
_des++, _src++;
}
return des;
}
int main(){
char a[] = "abcdefrt";
char b[] = "asdfgh";
Mymemcpy(a, a+1, strlen(a)+1);
Mymemcpy(b+1, b, strlen(b) + 1);//上述記憶體重疊情況
printf("%s\n", a);
printf("%s\n", b);
return 0;
}
輸出:
memmove模擬實現
只是在將上述記憶體重疊的情況單拎出來,從後往前拷貝。
情況為source首地址比destination首地址大,destination首地址比source尾地址大。
#include<stdio.h>
#include<assert.h>
void *Mymemmove(void* des, void* src, size_t size){
assert(des);
assert(src);
char *_des = (char *)des;//不能放在裡面,在外面宣告變數
char *_src = (char *)src;
if (_src < _des&&_des < (_src + size)){//先判定是哪種情況
_des += size-1;//指向最後一個元素的起始地址,如果加num指向的是最後一個元素的最後地址。
_src += size-1;
while (size--){//從後往前拷貝
*_des = *_src;
_des--, _src--;
}
}
else{
while (size--){//從前往後拷貝
*_des = *_src;
_des++, _src++;
}
}
return des;
}
int main(){
char a[] = "abcdefrt";
char b[] = "asdfgh";
Mymemmove(a, a + 1, strlen(a) + 1);
Mymemmove(b + 1, b, strlen(b) + 1);
printf("%s\n", a);
printf("%s\n", b);
system("pause");
return 0;
}
輸出: