c语言内存函数

目录

一.memcpy 使⽤和模拟实现 - 内存拷贝

1.使用

2.memcpy函数模拟实现

二.memmove使⽤和模拟实现

1.使用

2.memmove模拟实现

三.memset函数的使⽤ - 内存设置

四.memcmp函数的使⽤ - 进行内存比较


一.memcpy 使⽤和模拟实现 - 内存拷贝

1.使用

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


参数:3个
destination:目的地 - 里面内容是会变的
source:源头 - 里面内容是不会变的,用cosnt修饰
num:拷贝num个字节
源头拷贝到目的地,拷贝num个字节,参数void*,为什么?因为可能拷贝任何数据。
返回类型:void*

重要点:
• 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
• 这个函数在遇到 '\0' 的时候并不会停下来。strcpy拷贝到\0就停下来。
而memcpy你让我拷贝多大就拷贝多大,即使有\0照样拷贝。
• 如果source和destination有任何的重叠,复制的结果都是未定义的。//一般拷贝的是内存不重叠的情况
memcpy使用在内存不重叠拷贝,如果拷贝内容是重叠/同一块内存空间,就不要使用这个函数。

代码举例:memcpy函数整形拷贝

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	//将arr1中的1 2 3 4 5,拷贝到arr2中
	memcpy(arr2, arr1, 5 * sizeof(int));
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

代码举例:memcpy函数字符数数组拷贝

int main()
{
	char arr1[10] = "hello bit";
	char arr2[10] = { 0 };
	memcpy(arr2, arr1, 5);
	int i = 0;
	//for (i = 0; i < 5; i++)
	//{
	//	printf("%c", arr2[i]);
	//}
	printf("%s", arr2);

	return 0;
}

总结:我们可能传递字符的地址,也有可能传递整形地址,所以我们参数用void*类型。


代码举例:探究memcpy拷贝字符串遇到\0会不会拷贝后面字符

int main()
{
	char arr1[10] = "he\0lo bit";
	char arr2[10] = { 0 };
	memcpy(arr2, arr1, 5);
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%c ", arr2[i]);
	}
	
	return 0;
}

你让我拷贝几个就拷贝几个,不会管\0。

2.memcpy函数模拟实现

void* my_memcpy(void* dest, const void* src, size_t num)
{
	while (num--)
	{
		*(char*)dest = *(char*)src;//强制类型转换是临时的效果,下面也要强制类型转换
		//强制转换方法1:这种写法在有些编译器跑步过去
		//((char*)dest)++;
		//((char*)src)++; 

		//强制转换方法2:加完的结果放在dest和src
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	//将arr1中的4 5 6 7 8,拷贝到arr2中
	my_memcpy(arr2, arr1 + 3, 5 * sizeof(int));
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}

	return 0;
}


代码举例:探究memcpy拷贝同一块空间的结果?

void* my_memcpy(void* dest, const void* src, size_t num)
{
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };//12345,拷贝到34567上面去,内容重叠
	my_memcpy(arr1+2, arr1, 5 * sizeof(int));
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1 [i]);//1 2 1 2 1 2 1 8 9 10 
	}

	return 0;
}

因为拷贝3 4的时候被改成1 2,拷贝5 6的时候因为3 4被改成1 2所以5 6也是1 2 ,内容重叠拷贝结果就是错误。 

总结:
1.强制类型是临时的。
2.arr1数组拷贝到arr2数组里面,这是2块完全独立的空间,没有任何重叠和交错。
3.对应重叠的内存,交给memmove函数处理。

二.memmove使⽤和模拟实现

1.使用

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


memmove的参数和返回值跟memcpy差不多,所以使用方法也差不多。
代码举例:

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

2.memmove模拟实现

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

分析:如何拷贝?
空间重叠的时候:
1.从前向后拷贝 - dest在src左边 - dest < src
2.从后向前拷贝 - dest在src右边 - dest > src

空间不重叠的时候:就不需要考虑从前向后还是从后向前拷贝。
从后向前拷贝怎样拷贝?
1.分别拿到dest和src的末尾地址;+个num就可以拿到地址。

C语言中规定:
memcpy:拷贝的就是不重叠内存
memmove:拷贝的是重叠内存
但是在vs2022memcpy也可以实现重叠拷贝。

三.memset函数的使⽤ - 内存设置

void*  memset(void* ptr, int value, size_t num);
参数:
ptr:你要设置那块内存,从哪开始。
value:你要设置的值是什么
num:要设置为值的字节数
ptr指向的且num个字节内容设置成value值。

代码举例:字符数组

int main()
{
	char arr[10] = "hello bit";
	memset(arr, 'x', 5);
	printf("%s\n", arr);
	return 0;
}

memset 在设置的时候,是以字节为单位来设置的
代码举例:整形数组 - 想把数组10个元素的值改成1

int main()
{
	int arr[10] = { 0 };
	memser(arr, 1, 10);//错误:首先这个数组是40个字节,
	memser(arr, 1, 40);//错误:当你改成40,它会把每个字节改成1
	//0x01010101
	return 0;
}

总结:当你内存设置的值不满意的时候,就可以用memset来设置成你想要的值。
 

四.memcmp函数的使用 - 进行内存比较

int memcmp(const void* ptr1, const void* ptr2, size_t num);
这个函数跟strcmp非常相似,只不过它能进行内容比较,什么样的内存都能比较。
参数:
• ⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节。
返回值:
ptr1 > ptr2;>0
ptr1 = ptr2; 0
ptr1 < ptr2;<0

代码举例:整形比较

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 1,2,3,4,8 };
	int ret = memcmp(arr1, arr2, 17);
	printf("%d\n", ret);//-1

	return 0;
}

代码举例:字符比较

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcdef";
	int ret = memcmp(arr1, arr2, 7);
	printf("%d\n", ret);//0

	return 0;
}

  • 26
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值