日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C語言模擬實現memmove的示例代碼_C 語言

作者:ZHENGZJM ? 更新時間: 2023-02-05 編程語言

前言

上一篇我們介紹了memcpy和strcpy的區別,以及memcpy模擬實現,但這兩個庫函數都有一個缺點,那就是不能自己復制自己的內容

例子

這有一個數組arr,其元素分別為1、2、3、4、5、6、7、8、9、10,我們想將1、2、3、4復制到2的后面,從而將數組arr變成1、2、1、2、3、4、7、8、9、10

用memcpy嘗試

我們發現,跟我們預期的?1、2、1、2、3、4、7、8、9、10有出入。

錯誤原因

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memcpy(arr + 2, arr, 16);

memcpy實現過程

void* my_memcpy(void* dest, void* src, size_t count)
{
    void* ret = dest;
    while (count--)
    {
        *(char*)dest = *(char*)src;
        dest = (char*)dest + 1;
        src = (char*)src + 1;
    }
    return ret;
} 

當我們這樣操作時,src一開始指向1,1被復制到了3的位置上,后面指向2,2被復制到4的位置上,當src指針指向原來的3時,指向的內容變成了1,又將1復制到了5的位置上,當src指向原來的4時,指向的內容變成了2,又將2復制到了6的位置上。所以就出錯了。

用memmove嘗試

我們發現目的達到了,說明memmove適用于內存發生重疊的情況。那么memmove是怎么實現的呢?

memmove的模擬實現

整段代碼

void* my_memmove(void* dest, void* src, size_t count)
{
	void* ret = dest;
	if (dest < src)
	{
		while (count--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		while (count--)
		{
			*((char*)dest + count) = *((char*)src + count);
		}
	}
	return ret;
}

memmove的定義

由圖可知,memmove的返回值是目標地址,形勢參數分別是(目標地址,源頭地址,需要操作的字節數)

具體實現步驟

第一種情況(dest在src后),采用由后向前復制

由上面的錯誤分析,我們知道是因為后面要被復制過去的內容被更改了,還是用上面的例子做示范,我們從1開始復制的話,1會將3覆蓋掉,進而導致想將3復制到到5的位置上時,實際上是將1復制到5的位置上。

那么我們如果從4開始復制呢?我們由后至前進行復制,將4復制到6,再將3復制到5,這樣我們就不怕3、4被1、2覆蓋掉了。

我們要想先將4復制到6,先得將src指向4,dest指向6,然后再進行交換。我們用加傳過去的字節數來實現。

*((char*)dest + count) = *((char*)src + count);

我們想將指針前移,直接count減一就行,又因為我們要重復這一行為,所以我們使用while循環來實現。

        while (count--)
		{
			*((char*)dest + count) = *((char*)src + count);
		}

第二種情況(dest在src前),采用由前向后復制

如果dest在src前,我們還能用由后至前的方法復制嗎?

例如,我們將3、4、5、6向前移動2次,也就是將1、2、3、4、5、6、7、8、9、10變成3、4、5、6、5、6、7、8、9、10

我們發現并沒有成為我們想象當中的樣子。

錯誤原因

依然是要被復制的內容在被復制之前就被更改了,這里先將6移動到4,5移動到3,想將4移動到2時,實際上復制過去的是6,以此類推...

所以我們要采用由前向后復制的方法(【C語言】字符串拷貝函數(strcpy)與內存拷貝函數的不同及內存拷貝函數(memcpy)的模擬實現一文里有)

總結

memcpy不能實現自己拷貝自己,也就是不適用于內存疊加的情況。我們用memmove便可以解決這個問題。

對于memmove的模擬實現,核心思想就是將會被覆蓋的、要被復制的內容提前使用。這里分為兩種情況,一種是被復制的內容地址在目標內容地址的前面,另一種就是被復制的內容地址在目標內容地址的后面,對于前一種情況,我們使用由后至前進行復制的方法,對于后一種情況,我們使用由前至后進行復制的方法(dest在src后就由后向前。dest在src前,就由前向后)。

原文鏈接:https://blog.csdn.net/ZHENGZJM/article/details/128471331

欄目分類
最近更新