1. 程式人生 > 其它 >記憶體操作函式

記憶體操作函式

文章目錄

一.記憶體操作函式

記憶體操作函式適用於任何型別,但是它是以位元組為單位的。

1.memset函式

  1. 表現形式

在這裡插入圖片描述
適用於任何型別可以從void *看出。

  1. 作用
    將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函式

  1. 表現形式

在這裡插入圖片描述
引數為地址。

  1. 作用
    將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函式

  1. 表現形式
    在這裡插入圖片描述
    與memcpy相同。
  2. 作用
    也與memcpy相同,但是如果source與destination空間有重疊的地方,這個函式是起效的,可以得到想要的結果。
    用法與memcpy相同。

二.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;
}

輸出:
在這裡插入圖片描述