【C语言】内存函数模拟实现(memcpy,memmove,memcmp)

一.内存拷贝函数(memcpy)

内存拷贝函数(memcpy),顾名思义就是将一块内存的内容拷贝到另一块内存上。

函数返回值参数如下:

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

返回值为void无类型,其中函数参数部分:destination 为指向拷贝目的地的指针,source 为指向拷贝源头的指针,num 为需要拷贝的字节数,如8,就是拷贝8个字节。

1.使用实例

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

运行结果如下: 

 把arr1数组中的前8个字节拷贝到arr2数组中,因为int类型占4个字节,所以只拷贝两个数字到arr2数组中。

2.模拟实现

#include<stdio.h>
#include<assert.h>

void* my_memcpy(void* dest, const void* src, unsigned int num)
{
	assert(dest && src);
	void* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		((char*)dest)++;
		((char*)src)++;
	}
	return ret;
}

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

实现思路:

首先函数参数都为void类型,因为函数在传参数的时候有可能传int,有可能传char,也有可能传float,所以函数参数接收均用void类型,那既然函数参数的类型不确定,那应该怎么拷贝呢,所以可以全部强制转换为char类型,因为char类型占用一个字节,所以我们可以直接一个字节一个字节的拷贝。最后再用一个ret指针指向dest的起始位置并返回。

二.内存移动函数(memmove)

memmove函数其实和memcpy函数差不多,也是把一块内存内容拷贝到另一块内存上,但是memmove和memcpy不同的是,memmove可以处理拷贝源头拷贝目的地重合的情况。话不多说,上代码解释。

void* my_memcpy(void* dest, const void* src, unsigned int num)
{
	assert(dest && src);
	void* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		((char*)dest)++;
		((char*)src)++;
	}
	return ret;
}

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

 这里,我们想让 arr1 指向内容的后20个字节(即前五个数字)拷贝到 arr1+2 的位置上,也就是说 把1,2,3,4,5拷贝到3,4,5,6,7,8上,但是用这个memcpy函数并不能实现。拷贝完成后,打印结果如下:

原因如下: 

  

在拷贝的过程中,是一个一个的从前往后拷贝的,所以一开始是先把1拷贝到3的位置上,当拷贝完1之后,结果如下: 

所以当拷贝第三个数字的时候,并没有把3拷贝到5的位置,而是把1拷贝到了5的位置。

所以为了解决这个问题,我们可以从后往前拷贝先把5拷贝到7的位置,再把4拷贝到6的位置,以此内推,就可以顺利的完成拷贝。

但是如果情况如下呢,还能不能从后往前拷贝? 

 显然是不能。所以情况大致分为以下三种:

第一种,源头在目的地的签名,则从后往前拷贝。 

第二种,源头和目的地重叠,则从前往后和从后往前都可以。 

 

第三种,源头在目的地的后面,则从前往后拷贝 

基于这三种情况,所以我们统一为,当为第一种情况时 ,则从后往前拷贝,当为第二、三种情况时,我们从前往后拷贝

1.使用实例

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

 2.模拟实现

#include<stdio.h>
#include<assert.h>

void* my_memmove(void* dest, const void* src, int num)
{
	void* ret = dest;
	assert(dest && src);
	if (src > dest)
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			((char*)dest)++;
			((char*)src)++;
		}
	}
	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 };
	my_memmove(arr1+2, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

 三.内存比较函数(memcmp)

内存比较函数,用来比较两块内存的,函数定义如下:

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

ptr1为需要比较的第一个参数,ptr2为需要比较的第二个参数,size_t num为需要比较的字节数,其中这个函数的返回值为一个整形,若两个参数相同,则放回0,若第一个参数大于第二个参数,则返回1,若第一个参数小于第二个参数,则返回-1。

 1.使用实例

int main()
{
	float arr1[] = { 1.0,2.0,3.0 };
	float arr2[] = { 1.0,3.0 };
	int ret = memcmp(arr1, arr2, 8);
	printf("%d", ret);
	return 0;
}

程序运行结果如下: 

2.模拟实现

#include<stdio.h>
#include<assert.h>

int my_memcmp(void* arr1, void* arr2, int num)
{
	assert(arr1 && arr2);
	while (num--)
	{
		if (*(char*)arr1 == *(char*)arr2)
		{
			((char*)arr1)++;
			((char*)arr2)++;
		}
		else if (*(char*)arr1 > *(char*)arr2)
		{
			return 1;
		}
		else
		{
			return -1;
		}
	}
	return 0;
}

int main()
{
	float arr1[] = { 1.0,2.0,3.0 };
	float arr2[] = { 1.0,3.0 };
	int ret = my_memcmp(arr1, arr2, 8);
	printf("%d", ret);
	return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在C语言中,我们可以模拟实现memcpy函数memcpy函数的原型为void * memcpy(void * destination, const void * source, size_t num),它的作用是将源地址(source)指向的内存块的数据拷贝到目标地址(destination)指向的内存块中,拷贝的字节数由第三个参数num指定。 要实现memcpy函数,我们可以按照以下步骤进行操作: 1. 首先,我们需要创建一个与源内存块相同大小的目标内存块,并将目标内存块的地址保存在destination指针中。 2. 接下来,我们使用一个循环来逐字节地将源内存块的数据复制到目标内存块中,直到拷贝的字节数达到了num的值。 3. 最后,我们返回目标内存块的地址(destination指针),作为函数的返回值。 下面是一个示例的实现代码: ```c void *my_memcpy(void *destination, const void *source, size_t num) { char *dest = (char *)destination; const char *src = (const char *)source; for (size_t i = 0; i < num; i++) { dest[i = src[i]; } return destination; } ``` 在这个实现中,我们将destination和source指针都转换为char类型的指针,这样可以逐字节地进行数据拷贝。然后,我们使用一个循环来逐字节地将源内存块的数据复制到目标内存块中,直到拷贝的字节数达到了num的值。最后,我们返回目标内存块的地址作为函数的返回值。 这样,我们就实现了一个简单的memcpy函数的模拟实现。需要注意的是,这只是一个简单的示例实现,实际的memcpy函数可能会有更复杂的实现方式,具体实现可能因编译器和操作系统的不同而有所差异。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值