strcpy、memcpy、memmove的区别及实现

memcpy的用法 memcpy 函数用于 把资源内存(src所指向的内存区域) 拷贝到目标内存(dest所指向的内存区域) 立即下载

关于这3个函数,其实很多地方都有说明。然而很多地方说明不够详尽,或者比较独立,或者很多地方的介绍就是错误的。我这两天仔细研究了下,给出我自己的一些研究结果。

先看一下我自己的实现:

char* strcpy(char* dst,const char* src)
{
	char* rtn = NULL;
	if( (NULL!=dst)&&(NULL!=src) ){
		rtn = dst;
		while( '\0'!=(*dst++=*src++) )
		{
			NULL;
		}
	}
	return rtn;
}

void* memmove(void* dest,const void* src,size_t cnt)
{
	void* rtn = NULL;
	if( (NULL!=dest)&&(NULL!=src) )
	{
		rtn = dest;//返回地址为了实现串式运算
		//分支一情况:dst和src没有覆盖导致的问题
		if ( (dest<=src)||((char*)dest>=(char*)src+cnt) )
		{		
			while (cnt-- != 0)
			{				
				*(char*)dest = *(char*)src; 
				/*((char*)dest)+=1或者*((char*)dest)++都不会编译通过,
				这其实是仍然把dest当成了左值,
				只不过 在移动指针的时候每次移动sizeof(char)*/
				dest = (char*)dest + 1;
				src = (char*)src + 1;			
			}
		}
		else//分支二情况
		{
			dest = (char*)dest+cnt-1;
			src = (char*)src+cnt-1;
			char* pdest = (char*)dest;
			char* psrc = (char*)src;
			while(cnt--!=0)
			{
				*pdest-- = *psrc--;	
			}
		}
	}
	return rtn;
}

memmove()的分支一和分支二我采用了不同方式进行实现,为了体现void*是不能作为诸如+=、++、--这类操作符的左值的(事实上应该是在ANSI编码下不支持,GNU下可能支持不过我没试过,具体见我的 转载文章。

memcpy()我没有再贴代码,很多人都认为其实现方式和memmove()实现的分支一情况是一样的,这是一个佯谬。

事实上,我们采用了下面的测试代码在windows XP/VS2008下进行测试的情况并非这样:

	char a[10];
	for (int i=0;i<sizeof(a);i++)
	{
		a[i]=i;
		printf("%d,",a[i]);
	}
	printf("\n");
	memcpy(&a[4],a,6);
	for (int i=0;i<sizeof(a);i++){
		printf("%d,",a[i]);
	}
	printf("\n");


上面这个测试代码,很多人意想的结果应该如下:

0,1,2,3,4,5,6,7,8,9,
0,1,2,3,0,1,2,3,0,1,

但是实际输出结果如下:

0,1,2,3,4,5,6,7,8,9,
0,1,2,3,0,1,2,3,4,5,

就是说,memcpy()和memmove()的效果一样,系统没有想象的“那么傻”,编译器会处理覆盖问题。这样的话,很多人开始开始的想法是错误的么?

我于是又在嵌入式操作系统Vxworks下作了测试,然而这次的输出结果和“很多人”的想法一致,memcpy()没能再次完成处理覆盖的问题,这是为什么呢?

我们看一下库函数说明书:

void* memcpy(void* s, const void* ct, size_t n);
Copies n characters from ct to s and returns s. s may be corrupted if objects overlap.
void* memmove(void* s, const void* ct, size_t n);
Copies n characters from ct to s and returns s. s will not be corrupted if objects overlap.

看到了吧,人家只说memcpy()或许会出错,但是没说一定会出错。而windows显然早就注意到这一点,聪明但不合时宜地做了些优化!


Hi3516CV610硬件设计避坑指南:从电源模块到DDR布线实战解析 本文深入解析了Hi3516CV610硬件设计中的关键难点与实战技巧。重点剖析了电源架构的选型陷阱与PCB布局要点,详细阐述了DDR3/L高速布线的等长匹配、信号完整性及端接策略,并提供了MIPI接口与时钟电路的隔离设计指南。旨在帮助工程师规避常见设计错误,提升系统稳定性与可靠性。 阅读详情

相关推荐

Synopsys AXI VIP 从环境搭建到首个验证场景运行

本文详细介绍了Synopsys AXI VIP从环境搭建到首个验证场景运行的全过程,包括VIP安装、示例工程生成、验证环境解析、仿真调试技巧及进阶优化。特别针对AXI协议验证中的常见问题提供了实用解决方案,帮助工程师快速掌握这一SoC验证必备工具。

weixin_29185493的博客 342

memcpy使用

memcpy使用 C 标准库 - <string.h> 声明 C 库函数 ,函数声明如下: void *memcpy(void *str1, const void *str2, size_t n) // 从存储区 str2 复制 n 个字符到存储区 str1。 参数 str1 – 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。 str2 – 指向要复制的数据源,类...

feng_jiakai的博客 488

LabVIEW vs Python:谁更适合你的ATE自动化测试系统?实测对比与选型建议

本文深入对比了LabVIEW和Python在ATE自动化测试系统中的性能表现、开发效率和应用场景,帮助工程师根据实时控制需求、数据处理复杂度及团队技能做出最优选型决策。通过实测数据和典型案例,分析两者在硬件集成、系统性能和维护成本等方面的差异,并提供混合架构实施建议。

weixin_29240711的博客 276

Linux下ARM64 的 memcpy 优化与实现

Linux 内核用到了许多方式来加强性能以及稳定性,本文探讨的 memcpy 的汇编实现方式就是其中的一种,memcpy 的性能是否强大,拷贝延迟是否足够低都直接影响着整个系统性能。通过对拷贝函数的理解可以加深对整个系统设计的一个理解,同时提升自身技术实力。罗马不是一天建设而成的,Linux 内核的拷贝函数也不是一开始就是那么优秀,在 3.14 之前(具体多少版本忘记了),Linux 尚且没有完善对 ARM64 架构的支持,系统的内存拷贝函数就是一个简单的 c 语言版本,也就是目前内核中的通用拷贝函数。 #

smartvxworks的博客 3614

UE5 StateTree实战:用分层状态机重构你的AI行为逻辑(附蓝图配置避坑点)

本文详细介绍了UE5中StateTree分层状态机的实战应用,帮助开发者重构AI行为逻辑。通过核心概念解析、迁移策略、高级技巧和避坑指南,展示了StateTree在灵活性、可维护性和并行处理方面的优势,特别适合复杂AI行为的开发与优化。

weixin_42558257的博客 249

防雷防浪涌电路设计

通信线路或者电源线路通常会铺设到户外,一旦线路铺到户外后,就需要考虑防雷的问题了,那么怎么设计保护电路,能够防止雷电等浪涌对电路的破坏呢?

manhuami2007的博客 1万+

memset ,memcpy ,memmove,strcpy 的根本区别 与实现

memset ,memcpy ,memmove,strcpy 的根本区别 与实现 memset ,memcpy ,memmove,strcpy 的根本区别 与实现 - 邓维 - 博客园memset ,memcpy ,memmove,strcpy 的根本区别 与实现...

174

SceneSplat

目标:训练一个网络,输入高斯参数 → 输出与自然语言空间对齐的特征。考虑到标注语义的 3DGS 数据有限,作者设计了。策略,让模型在无标签场景上学到有用表征。都有一个与自然语言对齐的语义特征。这是整个方法的第一步,目标是让。

weixin_61091146的博客 1284

strcpy、memcpy和memmove的区别和实现

一、strcpy和memcpy都是标准C库函数,它们的区别如下: 1、复制的内容不同。strcpy只提供了字符串的复制;而memcpy一般提供内存的复制,即对所要复制的内容没有限制,例如:字符串、整型、结构体、类等。 2、函数原型不同。strcpy的函数原型为:char *strcpy(char *dest,const char *src);memcpy的函数原型为:void *memc

王婧的博客 975

C#怼倍福TwinCAT3:ADS协议封装实战(附完整读写源码+避坑清单)

变量名大小写敏感:PLC里定义的是GVL.bStart,你写GVL.BStart绝对读不到;数组访问格式:PLC数组是,C#里读单个元素要写,读整个数组不用写索引;句柄要释放:用创建的句柄,一定要用using包起来,否则会占着资源;PLC必须运行:哪怕变量定义对了,PLC没Run(只是Login)也读不到数据;路由配置:如果上位机和PLC不在一个网段,要在TwinCAT3里添加路由(Router→Edit Routes)。倍福ADS通信其实不难,核心就是“配置对+变量名写对+数据类型匹配”。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 949

Windows 10 本地硬盘变成了可弹出磁盘

今天新装了系统, 电脑是一个SSD+HHD, 没想到装好之后右下角显示可安全删除设备, 两个硬盘在那里. 这还得了. 查了一下午, 大致知道了是什么问题. Standard SATA AHCI controller使用高性能的硬盘模式就会把硬盘看作是一个可热插拔的存储器, 所以自然就会显示可弹出. 如果你的BIOS支持关闭HotSwap或者HotPlug, 那么直接关闭就可以了. 或者你直接在BIOS里把磁盘模式改为IDE, 不过这样就发挥不好你SSD的高性能了. 还有一种解决方法, 就是手动让系统把这两个

落日之城 4万+

memcpy、memmove、strcpy函数实现源码及区别

对于字符串操作的函数声明是在头文件 内,在编程中需要使用如下方式来引进: #include      1) void * memcpy(void* dest,  const void*  src,  size_t  n)             说明: 此函数功能为字符串内存拷贝,src为源字符,dest为目的字符串,拷贝的长度为n,调用此函数需用户保证src,dest所指向的长度

xiongwei 942

【C2000系列DSP的Bootloader详解】如何打包源文件为库文件且加密仅授权使用,一步步教你如何实现

如果想要在 TI 的 CCS 开发环境中为 C2000 系列 MCU 生成 lib 库文件,并对这些库文件进行加密保护,确保只有授权方(持有密钥)才能调用和使用,以此保护源代码的知识产权。

昔时扬尘处 177

strcpy、strncpy、memcpy、memmove之间的区别和实现

1.函数声明 char* strcpy(char *d_s, const char *s_s); char* strcpy(char *d_s, const char *s_s, size_t n); void* memcpy(void *d_s, const void *s_s, size_t n); void* memmove(void *d_s, const void *s_s, s...

follow_blast的博客 734

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

strcpy,memcpy,memmove的区别,编码实现memcpy和memmove。

strcpy,memcpy,memmove的区别,编码实现memcpy和memmove。

663

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

strcpy memcpy memmove区别和实现

memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中。 但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开销。 memmove的处理措施: (1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝 (2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝 (3)当源内存

amwpynnpyu的专栏 1032

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

C(C++) memmove和memcpy的实现以及区别所在(以及与strcpy的简单对比)

memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下: void *memcpy(void *dst, const void *src, size_t count); 描述:         memcpy()函数从src内存中拷贝n个字节到dest内存区域,但是源和目的的内存区域不能重叠。 返回值:        ...

u014288927的博客 567

常见内存拷贝函数:memcpy()、memmove()、strcpy()的实现及区别

转载:http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201322332592/ memcpy和memmove实现不同测试: memcpy不考虑内存重合问题:        即src        所以memcpy是正向copy n个字节的内容。 memmove考虑内存重合问题:       

u011980566的博客 1338

C/C++ memmove与memcpy的区别及实现

1.与字符串函数strcpy区别: memcpy与memmove都是对内存进行拷贝可以拷贝任何内容,而strcpy仅是对字符串进行操作。 memcpy与memmove拷贝多少是通过其第三个参数进行控制而strcpy是当拷贝至'\0'停止。 2.函数说明:         memcpy函数的功能是从源src所指的...

QTVLC的博客 394

C语言库函数:memcpy/memmove/strcpy/strncpy区别

@[TOP]memcpy/memmove/strcpy/strncpy区别 memcpy和memmove区别 memcpy和strcpy区别

u013073067的博客 1157

memcpy和memmove的模拟实现

首先来介绍的是memcpy memcpy函数语法 编辑播报 函数原型 void *memcpy(void *destin, void *source, unsigned n); 参数 destin-- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。 source-- 指向要复制的数据源,类型强制转换为 void* 指针。 n-- 要被复制的字节数。 返回值 该函数返回一个指向目标存储区destin的指针。 功能 从源so..

m0_60338933的博客 358
上一篇: C/C++语言void及void指针深层探索
下一篇: 互斥量和信号量的区别
RealOnlyme
博客等级 码龄19年 4粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值