内存操作函数memcpy、memmove、memcmp、memset

内存操作函数

一.memcpy

☀️函数介绍

void * memcpy ( void * destination, const void * source, size_t num );

1.函数作用:将source指向空间的前num个字节的数据拷贝到destination里面
2.不关心’\0’,不会因为’\0’而停下,它只关心拷贝多少个字节,即num。
3.要拷贝的内容和被拷贝的空间不可以重叠
4.相比较于strcpy函数,memcpy函数可以拷贝可以更多类型数据,如字符串、整型数组、结构体
5.要引用头文件#include
6.返回值是目标空间首元素地址

☀️ 模拟实现memcpy

#include
void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	while (num--)//num次
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr1, 4 * 5);
	int i = 0;
	for (i = 0;i < 10;i++)
	{
		printf("%d ", arr2[i]);
	}
}

运行结果:
内存操作函数memcpy、memmove、memcmp、memset_第1张图片
注:
1.为保证不对空指针进行加减解引用操作,要用到assert
2.为保证不通过指针修改被复制的内容,用const修饰源头内容空间地址
3.指针强制转化只能使用一次,当下用完当下失效,不可以写成(char ∗ * )++或(char ∗ * )–;++(char ∗ * )或–(char ∗ * )在某些编译器下不能这样写

二.memmove

按照memcpy中的例子,当我想把arr1中的12345拷贝到34567位置上,即同一数组中的A部分拷贝到B部分,A、B两部分有重叠会出现什么?
内存操作函数memcpy、memmove、memcmp、memset_第2张图片
预期效果:1 2 1 2 3 4 5 8 9 10
实际效果:1 2 1 2 1 2 1 2 1 2
memcpy函数只能拷贝不重叠、不相关的两个部分,想要实现重叠部分的拷贝,需要memmove函数

☀️1.函数介绍

void * memmove ( void * destination, const void * source, size_t num );

和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
用memmove函数实现重叠部分复制

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

运行结果:
内存操作函数memcpy、memmove、memcmp、memset_第3张图片

☀️2. 探究memmove的实现原理

(1)思路一:创建一个arr2来存放需要被拷贝的内容
缺点:浪费空间
(2)思路二:在同一空间内操作,将同一数组内相同大小且重叠的两部分A复制给B
情况一:A在前B在后,把A拷贝到B上(橙A蓝B)
内存操作函数memcpy、memmove、memcmp、memset_第4张图片
A在前B在后时,指针从后往前依次赋值,被复制的内容不会被覆盖。此时指针destination减指针source>0
情况二:A在后B在前,把A拷贝到B上(橙A蓝B)
内存操作函数memcpy、memmove、memcmp、memset_第5张图片

A在后B在前时,指针从前往后依次赋值,被复制的内容不会被覆盖。此时指针destination减指针source<0

结论:根据destination和source的大小关系决定从前往后拷贝还是从后往前

1.指针destination减指针source>0:从后往前拷贝
2.指针destination减指针source<0:从前往后拷贝

☀️模拟实现memmove

void* my_memmove(void* dest, void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	if (dest < src)//dest-src<0,从前往后
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	if (dest > src)//dest-src>0,从后往前
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr+2, arr, 5 * 4);
	int i = 0;
	for (i = 0;i < sizeof(arr) / sizeof(arr[0]);i++)
	{
		printf("%d ", arr[i]);
	}
}

运行结果:
内存操作函数memcpy、memmove、memcmp、memset_第6张图片
目标空间地址为arr,源内容地址为arr+2时,主函数为:

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

运行结果:
内存操作函数memcpy、memmove、memcmp、memset_第7张图片
注:
①其实在VS上memcpy可以实现重叠拷贝,但别的编译器上不一定,VS是个优等生,把没要求的也完成了,其他编译器不一定能实现
②memmove也可以实现不重叠部分的拷贝,也具有memcpy的功能

三.memcmp

☀️函数介绍

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

功能:比较从ptr1和ptr2指针开始的num个字节
返回值:
内存操作函数memcpy、memmove、memcmp、memset_第8张图片
用memcmp比较两字符串

#include 
#include 
int main()
{
	char buffer1[] = "DWgaOtP12df0";
	char buffer2[] = "DWGAOTP12DF0";
	int n;
	n = memcmp(buffer1, buffer2, sizeof(buffer1));
	if (n > 0) printf("'%s' 大于 '%s'.\n", buffer1, buffer2);
	else if (n < 0) printf("'%s' 小于 '%s'.\n", buffer1, buffer2);
	else printf("'%s' 等于 '%s'.\n", buffer1, buffer2);
	return 0;
}

运行结果:
内存操作函数memcpy、memmove、memcmp、memset_第9张图片
注:第三个参数size_t num是比较的字节数:
①前9个字节大小相同,返回0
内存操作函数memcpy、memmove、memcmp、memset_第10张图片

②arr1在第10个字节中存的是00,arr2存的是01,arr2>arr1,返回-1内存操作函数memcpy、memmove、memcmp、memset_第11张图片

四.memset

☀️函数介绍

内存操作函数memcpy、memmove、memcmp、memset_第12张图片
功能:以字节为单位设置想要的内容
例:

内存操作函数memcpy、memmove、memcmp、memset_第13张图片
注:10个字节,不是10个元素
内存操作函数memcpy、memmove、memcmp、memset_第14张图片

你可能感兴趣的:(c语言)