1. 程式人生 > >模擬實現memcpy和memmove函式

模擬實現memcpy和memmove函式

記憶體函式,memcpy是記憶體拷貝函式,memmove函式則是記憶體移動函式,這兩個函式的作用差不多,但是區別就在於memmove函式能夠反向拷貝,不用在意memcpy函式會遇到的問題。

下面我就具體解釋一下memcpy的侷限性:

舉個例子:給上一個陣列arr[] = 1 2 3 4 5 6 7 8 9,;現在你需要將 3 4 5 6拷貝到 5 6 7 8這幾個數的位置去。如果你正序拷貝,你會發現將3拷到5的位置,4拷到6的位置,但是你再繼續將5拷貝到7的位置的時候,你會發現5已經被改成了3,你再也無法將5拷貝到7的位置了。

下面我再用圖片演示一下:

首先指標指的是首地址,當指標指向3的時候

你準備將3拷貝到5的位置


5拷到7的時候,你會發現5所在的位置,已經被改成了3,這樣你再也無法拷貝5這個數字了


這樣你就會無法實現將3 4 5 6拷貝到 5 6 7 8。

所以,你需要進行反向的拷貝,就是從6開始向前拷貝,先將6拷到8的位置,再將5拷到7的位置,再將4拷到6的位置,再將3拷到5的位置,這樣就不會遇到無法完全拷貝的問題。

現在我們需要進行分析,需要知道什麼時候需要反向拷貝,什麼時候不需要。

你看,每當有你需要拷貝的數字的起始位置將要拷貝到你需要拷貝的位置發生了衝突,也就是將要被拷貝到的位置比將要拷貝數字的位置大,這樣你就可以反向拷貝了。

下面我用圖片演示一下:


你會看到,將3 4 5 6拷貝到5 6 7 8的位置,也就是

你會發現5所在的位置是大於3所在的位置的,如果是下面這樣的


將2 3 4 5拷貝到 6 7 8 9的位置,雖然他們也是符合上面的條件,但是你並不需要將其反向拷貝,但是反向拷貝也不會有什麼問題,所以,只要滿足上面的這個條件,你就可以反向拷貝。

當然,如果他是正向的,也就是不滿足上面的這個條件,你就直接拷貝就行了,和memcpy實現的原理一致。

程式碼附錄如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>


void* my_memcpy(void* dest, void* src,size_t n)
{
	void* ret = dest;
	char* str1 = (char*)dest;
	char* str2 = (char*)src;
	assert(dest);
	assert(src);
	while (n--)
	{
		*str1++ = *str2++;
	}
	return ret;
}

void* my_memmove(void* dest, void* src, size_t n)
{
	void* ret = dest;
	char* str1 = (char*)dest;
	char* str2 = (char*)src;
	assert(dest);
	assert(src);
	if (str1 > str2) 
	{
		while (n--)
		{
			*(str1 + n) = *(str2 + n);
		}
	}
	else
	{
		while (n--)
		{
			*str1++ = *str2++;
		}
	}
	return ret;
}

其中,src是指代源,而dest指代的是目標。

測試程式碼如下:

int main()
{
	int i = 0;
	int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int arr2[10] = { 0 };
	int arr3[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	my_memcpy(arr2, arr1, sizeof(arr1));
	my_memmove(arr3 + 5, arr3 + 4, 3 * sizeof(int));
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr3[i]);
	}
	system("pause");
	return 0;
}
測試結果我就不顯示了。還有什麼不足敬請指教。