天天看點

記憶體操作函數memcopy和memmove

我們以前在拷貝一個字元串時隻想到過strcpy()函數拷貝,但是這個函數在使用時存在一定的缺點,一方面它隻能用來拷貝字元串并不能拷貝其他類型的資料,另一方面它隻有在遇到'\0'時才結束拷貝,是以容易溢出。是以,就引入memcpy()這個記憶體操作函數。首先,先看一下二者的差別:

記憶體操作函數memcopy和memmove

memcpy:

1.函數原型:void *memcpy( void *dest, const void *src, size_t count );

2.了解:此函數在進行拷貝時,所給出的兩塊記憶體必須是不相關聯的

如果給一個類型已經給定的數組,例如 int arr1[]={1,2,3,4,5,6,7,8};要求将其複制到數組 int arr2[] 中去,我們一定想到的是下面這種辦法:

int *my_memcpy(int *dest,const int *src,int sz)
{
	int *pdest = dest;
	while(sz--)
	{
		*pdest = *src;
		src++;
		pdest++;
	}
	return dest;
}
           

試想想,假如就給了上邊這段代碼,如果要拷貝的是 char 型的字元串呢?!或者其他類型的數呢?!那這段程式就得一直被修改,這樣就特别麻煩,是以,在此代碼的基礎上做一些修改就可以打破這樣的局限性

void *my_memcpy(void *dest,const void *src,int sz)
{
	char *pdest = (char*)dest;
	const char *psrc = (const char *)src;
	assert(dest);
	assert(src);
	while(sz--)
	{
		*pdest = *psrc;
		psrc++;
		pdest++;
	}
	return dest;
}
           

顯然這是将類型改為了 void* 型的,這樣 void* 類型的指針就可以指向任意類型的指針,在函數内部将其強制類型轉換為 char* 類型同樣也是為了程式的實用性,使其在複制時是一個位元組一個位元組地拷貝

memmove:

1.函數原型: void *memmove( void *dest, const void *src, size_t count );

2.了解:将src所指向的字元串拷貝 count 個到 dest 所指向的字元串中,這兩塊記憶體可以是相關聯的,也可以是               不相關聯的。

讨論記憶體相關聯的情況———假設給定數組 int arr1[ ]={1,2,3,4,5,6,7,8},要将其輸出為12123678,即将123拷貝到從2 開始的位置:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

void *my_memmove(void *dest,const void *src,int count)
{
	char *pdest = (char *)dest;
	char *psrc = (char *)src;
	assert(dest);
	assert(src);
	if((pdest>psrc)&&(pdest<(psrc+count)))                  //dest指向于src和src+count的中間
	{
		while(count--)
		{
			*(pdest+count) = *(psrc+count);
			//pdest--;
			//psrc--;
		}
	}
	else
	{
		while(count--)
		{
			*pdest++ = *psrc++;
		}
	}
	return dest;
}


int main()
{
	int arr1[]={1,2,3,4,5,6,7,8};
	int sz = sizeof(arr1);
	int i = 0;
	my_memmove(arr1+2,arr1,3*sizeof(int));
	for(i=0; i<sizeof(arr1)/sizeof(arr1[0]); i++)
	{
		printf("%d ",arr1[i]);
	}
	system("pause");
	return 0;
}
           

這段代碼同樣存在一定的局限性,同樣也可以将指針類型改為void* 類型,但需注意的是 void* 類型的指針不能自加自減,也不能解引用,是以必須将其強制類型轉換

memset :

1.函數原型:void *memset( void *dest, intc, size_tcount );

2.了解:此函數是對 dest 所指向的某一塊記憶體的前 count 個位元組初始化為c對應的ASCCII值

void *my_memset(void *dest,int ch,size_t count)
{
	char *pdest = (char *)dest;
	while(count--)
	{
		*pdest = ch;
		pdest++;
	}
	return dest;
}
           

繼續閱讀