十七、C语言内存函数

1 memcpy函数的使用和模拟实现

//memcpy函数的声明
void* memcpy(void* destination, const void* source, size_t num);

memcpy函数可以给内存进行拷贝,由于不知道要拷贝的内存中存放的是哪一种类型的数据,所以memcpy函数的返回类型设置成了void*

memcpy函数在执行时,会从source指向的位置开始向后复制num个字节的数据到destination指向的位置,期间在遇到\0时并不会停下来,最后返回destination的起始位置。

#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[10] = { 0 };
	int arr2[] = { 1,2,3,4,5,6,7,8 };
	memcpy(arr1, arr2, 20); 
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

输出结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:memcpy函数可以处理不重叠的内存之间的数据拷贝,如果sourcedestination在内存上存在重叠,那么复制的结果将是未定义的。

有时候标准库中的memcpy也能实现重叠拷贝(比如VS编译器),但是并不代表所有编译器的库函数中的memcpy都能实现重叠拷贝。

#include <stdio.h>
#include <string.h>
#include <assert.h>
void* my_memcpy(void* dest, void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	while (num)
	{
		//拷贝一个字节
		*(char*)dest = *(char*)src;
		//由于强制类型转换是临时的,所以想要地址+1也要强制转换
		dest = (char*)dest + 1;
		src = (char*)src + 1;
		num--;
	}
	return ret;
}
int main()
{
	int arr1[10] = { 0 };
	int arr2[] = { 1,2,3,4,5,6,7,8 };
	char arr3[] = { 'a','b','c' ,'d' ,'e' ,'f','g','h','i' };
	char arr4[] = "abcde";
	my_memcpy(arr1, arr2, 20); 
	my_memcpy(arr3, arr4, 7);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	printf("\n");
	printf("%s\n", arr3);
	return 0;
}

输出结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2 memmove函数的使用和模拟实现

//memmove函数的声明
void* memmove(void* destination, const void* source, size_t num);

memcpy函数相似,memmove函数也可以给内存进行拷贝,不同的是memmove函数处理的soucedestination的内存块是可以重叠的。

例:

#include <stdio.h>
#include <string.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr + 2, arr, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

输出结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

memmove函数模拟实现:

#include <stdio.h>
#include <string.h>
#include <assert.h>
void* my_memmove(void* dest, void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	if (dest < src)//从前往后拷
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else//从后往前拷
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr1, arr1 + 2, 20);
	my_memmove(arr2 + 2, arr2, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	printf("\n");
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
	return 0;
}

输出结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3 memset函数的使用

//memset函数的声明
void* memset(void* ptr, int value, size_t num);

memset函数能将ptr指向的内存块的前num个字节设置为value

注意:memset是以字节为单位设置内存值的。

例:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "hello world";
	memset(arr, 'x', 5);
	printf("%s\n", arr);
	return 0;
}

输出结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4 memcmp函数的使用

//memcmp函数的声明
int memcmp(const void* ptr1, const void* ptr2, size_t num);

memcmp函数能够比较从ptr1ptr2指针指向的位置开始向后的num个字节,其返回值如下:

返回值含义
<0两个内存块中不匹配的第一个字节ptr1中的值小于ptr2中的值(如果评估为无符号字符值)
0两个内存块的内容相等
>0两个内存块中不匹配的第一个字节在ptr1中的值大于在ptr2中的值(如果评估为无符号字符值)

例:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "aacdef";
	char arr2[] = "abcdef"; 
	char arr3[] = "abcdef";
	char arr4[] = "accdef";
	int ret1 = memcmp(arr1, arr2, 2);
	int ret2 = memcmp(arr2, arr3, 2);
	int ret3 = memcmp(arr4, arr3, 2);
	printf("%d\n", ret1);
	printf("%d\n", ret2);
	printf("%d\n", ret3);
	return 0;
}

输出结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HackerKevn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值