memcpy函数的作用以及四种用法,后面那三种很巧妙(看完不亏)

函数 - memcpy( )

一、前言

  memcpy() 函数到底是干什么嘞呢😕一般从函数名字里就可以看出函数的功能,此函数即可,mem是memory的缩写,cpy是copy的缩写。二者合体就是内存复制的意思。咋个复制法呢🤔我们先来看官方解释🌞

二、官方解释

  以下解释来源于:https://cplusplus.com/reference/cstring/memcpy/?kw=memcpy
此函数的声明如下:

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

size_t表示无符号整型。有了函数声明我想大家已经构想出函数的实现了(❁´◡`❁)。

<>这是官方英文解释:

此处为英文原文档

<>这是翻译后的:

此处为google浏览器翻译结果
概括一下

将 num 字节值从源指向的位置直接复制到目标内存块。
源指针和目标指针所指向的对象的基础类型与此函数无关;结果是数据的二进制副本。
该函数不检查源中是否有任何终止空字符 - 它始终精确地复制数字字节。
为避免溢出,目标参数和源参数所指向的数组的大小应至少为 num 个字节,并且不应重叠(对于重叠的内存块,memmove 是一种更安全的方法)。
函数memcpy从source的位置开始向后复制num个字节的数据到destinatation
这个函数在遇到 ‘\0’ 的时候并不会停下来。
如果source和destination有任何的重叠,复制的结果都是未定义的。

这是官方给的例子,举了结构体的拷贝:

/* memcpy example */
#include <stdio.h>
#include <string.h>
struct {
  char name[40];
  int age;
} person, person_copy;
int main ()
{
  char myname[] = "Pierre de Fermat";
  /* using memcpy to copy string: */
  memcpy ( person.name, myname, strlen(myname)+1 );
  person.age = 46;
  /* using memcpy to copy structure: */
  memcpy ( &person_copy, &person, sizeof(person) );
  printf ("person_copy: %s, %d \n", person_copy.name, person_copy.age );
  return 0;
}

运行结果如下:
在这里插入图片描述

三、参数解析

参数destinationsourcenum
解析目标空间地址待拷贝空间源地址待拷贝内容字节数

四、功能实现

看完官方文档,我想我们可以自己尝试实现一下这个功能

void* My_memcpy(void* dest,const void* src, size_t num)
{
	assert(dest && src); //断言一下,就像倒水一样,看看有没有存水空间
	void* ret = dest; //把目标首地址记下来,最后return的就是它
	while (num--)
	{	//这个操作就是一个一个复制
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret; //返回目标首地址
}

大家可以思考一下这个实现存在什么问题🤔

五、用法

<1> 第一种用法

描述:将指定长度的字符串复制到目标字符串。(有长度限制)
参数:memcpy(target, str , sizeof(char) * n)
解释:将字符串str的前n个字符复制到target中。
其实这里 sizeof(char) * n 可以直接写成 n,因为一个字符占一个字节

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	char target[100];
	char str[]="I am handsome";
	memcpy(target,str,7);
	cout<< "复制之后的结果:%s" << target << endl;
	return 0;	
}

运行结果:
在这里插入图片描述

<2> 第二种用法

描述:将指定区间的字符复制到目标字符串。
参数:memcpy(target, str + n1 , sizeof(char) * n2)
解释:将str中从第3个字符开始的连续5个字符复制到target中。

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	char target[100];
	char str[]="I am handsome";
	memcpy(target,str + 2, sizeof(char) * 5);
	cout<< "复制之后的结果:%s" << target << endl;
	return 0;	
}

运行结果:
在这里插入图片描述

<3> 第三种用法

描述:将指定长度的字符覆盖到到目标字符串。
参数:memcpy(target, str , sizeof(char) * n)
解释:将字符串str的前n个字符覆盖到target中。

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	char target[] = "I am handsome";
	char str[]="*****";
	memcpy(target,str, sizeof(char) * 5);
	cout<< "复制之后的结果:%s" << target << endl;
	return 0;	
}

运行结果:
在这里插入图片描述

<4> 第四种用法

描述:将指定长度的字符覆盖到到目标字符串的指定位置
参数:memcpy(target + 2, str , sizeof(char) * 2)
解释:将字符串str的前2个字符覆盖到target从第三个开始的位置出。

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	char target[] = "I am handsome";
	char str[]="*****";
	memcpy(target + 2,str, sizeof(char) * 2);
	cout<< "复制之后的结果:%s" << target << endl;
	return 0;	
}

运行结果:
在这里插入图片描述
  看到这,大家应该会想到,还可以将待复制地址的指定区间覆盖到目标地址的指定区间。下面就不再展示了。

在这里插入图片描述

六、总结

但是用这个函数的时候我们要注意三个点

1. 一定要注意memcpy函数第三个参数传的是待传内容的字节数
  举个例子,如果我们想把整形数组arr1中前五个元素传中arr2,在memcpy就要写20。为什么呢?因为arr1为整型数组,其中包含的元素也是整型,是4个字节。而我们要传递五个整型,所以就是4*5个字节

2. 目的空间大小一定要能容纳memcpy所拷贝的内容
  如果拷贝在内容超过目的空间大小,那么就会溢出 编译器会报出警告

3. 尽量避免dest和src所指向的地址有内存重叠的部分这就是上面自己实现时没有考虑到的情况
例如:我们想把arr1中1、2、3分别拷贝到3、4、5的位置时,就出现了内存重叠的现象。
在这里插入图片描述

(其实,C语言自带的memcpy函数避免了这个问题(从低地址向高地址复制的时候,出现重叠,导致得到远离目标的结果))

  到这里,memcpy( ) 函数就讲解完毕了,感谢您观看至此,若发现错误,敬请评论区自由批评指正,吾自当洗耳恭听并改正哈哈;如果大家觉得我写得还不错的话,还请点一波赞哈哈,您的肯定是对我创作的鼓励和支持,是我进一步创作的动力(❁´◡`❁)!

参考文献

  1. https://blog.csdn.net/weixin_53564801/article/details/123933689?spm=1001.2101.3001.6650.5&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-5-123933689-blog-122409857.235%5Ev38%5Epc_relevant_anti_t3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-5-123933689-blog-122409857.235%5Ev38%5Epc_relevant_anti_t3&utm_relevant_index=10
  2. https://blog.csdn.net/m0_65601072/article/details/125904069
  • 26
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_a_yang

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

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

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

打赏作者

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

抵扣说明:

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

余额充值