memcpy与memmove函数介绍以及各自的模拟实现

目录

一.memcpy函数

1.介绍

功能:

2.模拟实现

基本要求:

实现:

二.memmove函数

1.介绍

功能

2.模拟实现

基本要求

 分析:

实现 


一.memcpy函数

1.介绍

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

为保证函数的泛用性,函数类型,参数类型均为无符号型。

功能:

将用户输入字节的值从的位置直接复制到目标指向的内存块中。但对于重叠的数据复制本函数会出现错误。

1.从arr1复制一定数量的数字到arr2中

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

 2.arr1中的重叠复制,5,6,7,8,9五个数字复制到3,4,5,6,7的所在位置上。

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

结果并不是理想中的1,2,5,6,7,8,9,8,9,10的结果。原因是在复制过程中,导致数据丢失。 所以memcpy函数不适合重叠复制。

2.模拟实现

基本要求:

1.保证函数的泛用性

2.实现给定地址之间的字符复制

实现:

1.main函数书写

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

2.模拟函数my_memcpy声明

void* my_memcpy(void* dest, const void* str, size_t num);

3.my_memcpy函数实现

a.因为函数参数类型均为无符号型,所以需要强制类型转换,转化为char类型效果是最好的。

复制过程中要保证原数据不发生变化,所以需要用const(不能通过该指针修改所指向的数据)修饰。

b.函数需要返回目标数组的地址,但在后续的变换中目标数组地址会向后移动。所以我们需要一个指针来存储最开始的地址值。

c.int为4字节,char为1字节。移动一个整形数据,需要循环四次。所以给需要给复制数据个数乘以四,即可解决循环问题。

void* my_memcpy(void* dest, const void* str, size_t num)
{
    assert(dest && str);
    //assert对传进来的指针是否为空指针进行检测
    // 如果非空指针不进行任何操作
    // 如果是空指针就捕捉到这种错误
    // 并打印出错误信息,终止程序执行。
    char* ret = (char*)dest;
    while (num--)
    {
        *(char*)dest = *(char*)str;
        dest = (char*)dest + 1;
        str = (char*)str + 1;
    }
    return ret;
}

4.完整代码

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* str, size_t num)
{
    assert(dest && str);
    //assert对传进来的指针是否为空指针进行检测
    // 如果非空指针不进行任何操作
    // 如果是空指针就捕捉到这种错误
    // 并打印出错误信息,终止程序执行。
    char* ret = (char*)dest;
    while (num--)
    {
        *(char*)dest = *(char*)str;
        dest = (char*)dest + 1;
        str = (char*)str + 1;
    }
    return ret;
}
void* my_memcpy(void* dest, const void* str, size_t num);
int main()
{
    int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr2[10] = { 0 };
    my_memcpy(arr2, arr1, 10*4);
    for (int i = 0; i < 10; i++)
    {
        printf("%d ", arr2[i]);
    }
    return 0;
}

二.memmove函数

1.介绍

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

 为保证函数的泛用性,函数类型,参数类型均为无符号型。

功能

将一定数量的值从的位置复制到目标指向的内存块中。复制就像使用了中间缓冲区一样,允许目标重叠。

1.从arr1+4开始向后五个数复制到以arr1+2开始的位置。

#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	             //1,2,5,6,7,8,9,8,9,10
	int arr2[] = { 0 };
	int n;
	scanf("%d", &n);
	menmove(arr1 + 2, arr1 + 4, n * 4);
	for (int i = 0; i != '\n'; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

2.结果 

2.模拟实现

基本要求

a.因为函数参数类型均为无符号型,所以需要强制类型转换,转化为char类型效果是最好的。

复制过程中要保证原数据不发生变化,所以需要用const(不能通过该指针修改所指向的数据)修饰。

b.函数需要返回目标数组的地址,但在后续的变换中目标数组地址会向后移动。所以我们需要一个指针来存储最开始的地址值。

c.int为4字节,char为1字节。移动一个整形数据,需要循环四次。所以给需要给复制数据个数乘以四,即可解决循环问题。

d.memmove函数是如何实现重叠复制的呢?这跟源地址和目标地址的前后有关系。

 分析:

实现 

 1.main函数

#include<stdio.h>
#include<string.h>
#include<assert.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	             //1,2,5,6,7,8,9,8,9,10
	int arr2[] = { 0 };
	my_menmove(arr1 + 2, arr1 + 4, 5 * 4);
	for (int i = 0; i != '\n'; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

2.函数声明

void* my_menmove(void* dest,const void* str, size_t num);

3.my_memmove函数

void* my_menmove(void* dest,const void* str, size_t num)
{
	assert(dest && str);
	char* ret = (char*)dest;
		if (dest < str)//前—>后
		{
			while (num--)
			{
				*(char*)dest = *(char*)str;
				dest = (char*)dest + 1;
				str = (char*)str + 1;
			}
		}
		else//后—>前
		{
			while (num--)
			{
				*((char*)dest + num) = *((char*)str + num);
                //加num,当num=20,经过--变成19。此时dest和str经过强制转化均为1
                //加19刚好满20,指向复制数字个数的最后一个
			}
		}

	return ret;

}

4.完整代码

#include<assert.h>
#include<string.h>
#include<stdio.h>
void* my_menmove(void* dest,const void* str, size_t num)
{
	assert(dest && str);
	char* ret = (char*)dest;
		if (dest < str)//前—>后
		{
			while (num--)
			{
				*(char*)dest = *(char*)str;
				dest = (char*)dest + 1;
				str = (char*)str + 1;
			}
		}
		else//后—>前
		{
			while (num--)
			{
				*((char*)dest + num) = *((char*)str + num);
			}
		}

	return ret;

}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	             //1,2,5,6,7,8,9,8,9,10
	int arr2[] = { 0 };
	my_menmove(arr1 + 2, arr1 + 4, 5 * 4);
	for (int i = 0; i != '\n'; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

                                                  你的关注、点赞,是我写文章 动力。

最后,谢谢观看!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值