C语言一些内存函数说明及模拟实现

一、memcpy库函数的使用和模拟实现

我们可以看到memcpy有3个参数,memcpy的功能是从source指向的内存空间的起始位置取num个字节的内容复制到destination指针指向的内存空间,最后返回destination指向内存空间的地址。

需要注意的是:如果source指向的内存空间与destination指向的内存空间有重叠的部分,memcpy处理的结果是未定义的,我们也可以这样理解,memcpy函数只需处理不重叠时的内存拷贝。后面内容会说到专门处理重叠问题的库函数memmove。

我们先看一下memcpy库函数的基本使用。请看代码:

//使用memcapy
#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 6,7,8,9,10 };
	//arr1指向的内存空间起始位置开始复制20字节内容到arr2中去
	memcpy(arr2, arr1, 20);
	//打印观察
	for (int i = 0;i < 5;i++)
		printf("%d ",arr2[i]);//此时打印1 2 3 4 5
	return 0;
}

根据所描述的功能,我们可以写一个函数来模拟实现它,接下来请看代码:

//模拟实现memcpy
#include <assert.h>
#include <stdio.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);//判断指针的有效性
	void* ptr = dest;//保存目的内存起始地址,防止丢失
	while (num--)
	{
		//因为dest和src的类型都是void*,所以我们可以将其强制转换成char*类型
		//一个字节一个字节的进行拷贝,直到num等于0为止
		*(char*)dest = *(char*)src;
		((char*)dest)++;
		((char*)src)++;
	}
	return ptr;
}
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 6,7,8,9,10 };
	//arr1指向的内存空间起始位置开始复制20字节内容到arr2中去
	my_memcpy(arr2, arr1, 20);
	//打印观察
	for (int i = 0;i < 5;i++)
		printf("%d ",arr2[i]);//此时打印1 2 3 4 5
	return 0;
}

二、memmove库函数的使用和模拟实现

前面我们说到memcpy函数对内存重叠问题是未定义的,它只需解决未重叠的问题即可,那么memmove函数的出现则是专门用来解决内存重叠问题。

接下来,我们看一下memmove的基本使用。请看代码:

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

我们也可以模拟实现它的功能。

接下来,请看具体代码:

//模拟实现memmove
#include <assert.h>
#include <stdio.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ptr = dest;//保存目的内存起始地址,防止丢失
	if (src < dest)
	{
		//后->前
		while (num--)
			//找到最后一个字节的位置开始向前复制
			*((char*)dest + num ) = *((char*)src + num );
	}
	else
	{
		//前->后
		while (num--)
		{
			//因为dest和src的类型都是void*,所以我们可以将其强制转换成char*类型
			//一个字节一个字节的进行拷贝,直到num等于0为止
			*(char*)dest = *(char*)src;
			((char*)dest)++;
			((char*)src)++;
		}
	}
	return ptr;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9 };
	my_memmove(arr1 + 2, arr1, 20);
	for (int i = 0;i < 9;i++)
		printf("%d ", arr1[i]);//输出1 2 1 2 3 4 5 8 9
	return 0;
}

三、memset库函数的使用和模拟实现

 memset有3个参数,ptr是指向要填充的内存块的指针,value是要设置的值。该值以 int 形式传递,但该函数使用该值的无符号字符转换来填充内存块。num是要设置的字节的个数,返回起始位置的地址。

具体运用请看代码:

//使用memset
int main()
{
	int arr[] = { 1,2,3,4,5,6 };
	memset(arr, 0, 24);//将数组的内容全部设置为0
	for (int i = 0;i < 6;i++)
	{
		printf("%d ",arr[i]);//打印结果为0 0 0 0 0 0
	}
	return 0;
}

下面我们可以模拟实现它,请看具体代码:

//模拟实现memset
#include <assert.h>
#include <stdio.h>
void* my_memset(void* ptr, int value, size_t num)
{
	assert(ptr);//判断指针的有效性
	void* tmp = ptr;
	while (num--)
	{
		//将ptr强制转换为char*类型
		//一位一位设置,直到num为0
		*(char*)ptr = (unsigned char)value;
		((char*)ptr)++;
	}
	return ptr;
}
int main()
{
	//以int数据为例
	//int arr[] = { 1,2,3,4,5,6 };
	//my_memset(arr, 0, 24);//将数组的内容全部设置为0
	//for (int i = 0;i < 6;i++)
	//{
	//	printf("%d ",arr[i]);//打印结果为0 0 0 0 0 0
	//}
	
	//以字符串为例
	char arr[] = "abcdef";
	my_memset(arr, 'k', 6);
	printf("%s\n",arr);//打印结果为kkkkkk
	return 0;
}

四、memcmp库函数的使用和模拟实现

 

 memcmp库函数的功能是比较从ptr1和ptr2指针指向的位置开始,向后的num个字节的内容。

它们的返回值有以下说明。

 具体运用请看代码:

我们会发现它和strncmp非常相似,但我们要注意strncmp只能比较字符串,而memcmp可以比较任何类型,不仅限于比较字符串。

下面我们来模拟实现它,请看代码:

//模拟实现memcmp
#include <stdio.h>
#include <assert.h>
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	assert(ptr1 && ptr2);//保证指针有效性
	assert(num > 0);//num必须要大于0
	while (*(char*)ptr1 == *(char*)ptr2)
	{
		num--;
		if (num == 0)//如果num次数比较完了进循环就说明它们相等,返回0
			return 0;
		((char*)ptr1)++;
		((char*)ptr2)++;
	}
	return *(char*)ptr1 - *(char*)ptr2;
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcefg";
	int ret = my_memcmp(arr1, arr2, 3);
	if (ret > 0)
		printf("'%s' is greater than '%s'.\n", arr1, arr2);
	else if (ret < 0)
		printf("'%s' is less than '%s'.\n", arr1, arr2);
	else
		printf("'%s' is the same as '%s'.\n", arr1, arr2);
	return 0;
}

到这里就结束了,祝大家天天开心! 

  • 21
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值