【C语言】内存操作函数


1.memcpy

strcpy只能拷贝字符串,而memcpy不仅于此,还可以拷贝其他类型的内容。

在这里插入图片描述
例子

int main()
{
	int arr1[10] = { 0 };
	int arr2[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memcpy(arr1, arr2, sizeof(int)*5);//可以了解为从arr2开始,拷贝20个字节到arr1指向的空间
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", *(arr1 + i));
	}
	return 0;
}

结果
1 2 3 4 5

注意
(1)目标数组和源数组都得保证足够大。
(2)这个函数若还没拷贝完num个字节,遇到’\0’并不会停下来。
(3)如果要从源数组的其他位置开始拷贝,可以修改起始地址,例如memcpy(arr1,arr2+4,sizeof(int)*5)。


2.模拟实现memcpy

void* my_memcpy(void* dest, const void* sour, int num)
{
	assert(dest && sour);
	void* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)sour;
		dest = (char*)dest + 1;
		sour = (char*)sour + 1;
	}
	return ret;
}
int main()
{
	int arr1[10] = { 0 };
	int arr2[10] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memcpy(arr1, arr2, sizeof(int)*5);//可以了解为从arr2开始,拷贝20个字节到arr1指向的空间
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", *(arr1 + i));
	}
	return 0;
}

结果
1 2 3 4 5

疑惑
(1)如果自己给自己拷贝会是怎样的结果?(即dest和sour有重叠部分)例如memcpy(arr1+2,arr1,20)

其可能出现以下两种结果:
1 2 1 2 3 4 5 8 9 10
1 2 1 2 1 2 1 8 9 10

(2)为什么会出现第二种结果?当你按图中的步骤做时
在这里插入图片描述
(3)这样的结果是达不到我们的预期的,如何才能得出第一种结果?
在同数组中,当sour在dest的左边时,将sour指向的字节按从前往后的方式拷贝到dest指向的位置,肯定会发生覆盖,从而导致重复。那我们就对源数据从后向前处理;当sour在dest的右边时,我们对源数据从前向后处理。
(4)以上涉及memmove的模拟实现,我们先了解下memmove


3.memmove

memmove相当于加强版的momcpy,也是拷贝内存块,但它能实现内存块的重叠拷贝。
例子

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memmove(arr1 + 2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(arr1 + i));
	}
	return 0;
}

结果
1 2 1 2 3 4 5 8 9 10

在这里插入图片描述


4.模拟实现memmove

void* my_memmove(void* dest, void* sour, int num)
{
	assert(dest && sour);
	void* ret = dest;
	if (sour > dest)
	{
		while (num--)
		{
			*(char*)dest = *(char*)sour;
			sour = (char*)sour + 1;
			dest = (char*)dest + 1;
		}
	}
	else
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)sour + num);
		}
	}
	return ret;
}
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	my_memmove(arr1 + 2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(arr1 + i));
	}
	return 0;
}

结果
1 2 1 2 3 4 5 8 9 10

注意
要拷贝的数组要有足够的空间存放被拷贝的内容,防止越界访问


5.memcmp

在这里插入图片描述
这个函数的返回值和strcpy的返回值相同,如果当ptr1指向的字节等于ptr2指向的字节,那么两者++,若早已比较num个字节,则返回0;如果当ptr1指向的字节大于ptr2指向的字节,就返回大于0的数字;如果当ptr1指向的字节小于ptr2指向的字节,则返回小于0的数字。
例子

int main()
{
	int arr1[] = { 1,2,3 };
	int arr2[] = { 1,2,5 };
	printf("%d", memcmp(arr1, arr2,9));//比较9个字节
	//已只数据在内存中的存储方式是小端存储(低位字节序放在低地址处,高位字节序放在高地址处)
	//arr1在内存中的存储:01 00 00 00 02 00 00 00 03 00 00 00
	//arr2在内存中的存储:01 00 00 00 02 00 00 00 05 00 00 00
	//比较前9个字节,到第九个字节时05>03,所以arr1<arr2,返回小于0的数字
	return 0;
}

结果
-1


6.memset

在这里插入图片描述
例子

int main()
{
	char arr[] = "hello world";
	//将hello改为xxxxx
	memset(arr, 'x', 5);
	printf("%s\n", arr);
	//将world改为yyyyy
	memset(arr + 6, 'y', 5);
	printf("%s\n", arr);
	return 0;
}

结果
xxxxx world
xxxxx yyyyy

注意
(1)memset是以字节为单位处理的
(2)memset通常用来初始化数据

猜你喜欢

转载自blog.csdn.net/Zhuang_N/article/details/128839890