内存函数memcpy和memmove的讲解

2024-03-18 04:44

本文主要是介绍内存函数memcpy和memmove的讲解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是memcpy函数

在cplusplus官网上是这样介绍的
在这里插入图片描述
这里的意思是memcpy会从开始位置复制若干个字节到终止的内存位置,这个函数在遇到\0时不会停下来,如果在复制的时候出现内存重叠的时候结果都是未定义的,也就是说我们有一个数组arr里面放有1,2,3,4,5,6个元素,现在我们把他复制20个字节到arr2数组里面,arr2里面就存放了1,2,3,4,5个元素,因为这个是按字节复制的一个整形占4个字节那么就是5个元素,如果把arr数组从首地址开始,复制到arr+2那个空间里面,这里就发生了内存重叠,结果就是未定义的。我们来举一个例子,来看看具体怎么使用。

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

这个函数包含的头文件是string.h,我们看看运行结果。
在这里插入图片描述
这里我们发现我们成功复制了arr数组里面的20个字节到arr2里面并成功打印出了1,2,3,4,5这个元素,我们这里数组给的空间比较大,后面空余的空间会自动补0。
接下来我们看看memcpy函数的模拟实现

memcpy函数的模拟实现

我们来看看这张图
在这里插入图片描述
我们看到这个函数需要传的参数都需要转换成void的指针,这是因为我们不仅仅只能拷贝整形数据,还要能拷贝字符型数据等,所以我们要用void指针,下面来看看代码

#include <stdio.h>
#include <assert.h>
void* my_memcpy(void* start, void* go_to, size_t num)
{void* ret = go_to;assert(start != NULL && go_to != NULL);for(num ; num > 0 ;num--){*(char*)go_to = *(char*)start;go_to = (char*)go_to + 1;start = (char*)start + 1;}return ret;
}
int main()
{int arr1[] = {1,2,3,4,5,6,7,8,9,10};int arr2[10] = { 0 };int num = 20;my_memcpy(arr1, arr2,num);for (int i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}

这里我们用start来代替官网中使用的scr,goto代替destination

void* my_memcpy(void* start, void* go_to, size_t num)

这里的参数就对应上面说的要变成void指针
首先把go_to的首地址存起来,我们最终是要返回go_to的,然后为了保证指针的有效性我们用assert来断言一下,防止指针为空然后下面就进入到拷贝环节了,我们用了一个for循环我们把他强制转换为char
这是因为char*类型的指针解引用他只向后偏移一个字节,这样我们可以拿这一个字节做一个标准一个单位来完成我们整形,字符型等元素的拷贝。最后就是打印数组了。下面是memmove函数讲解,这个的模拟实现要复杂一些。

什么是memmove函数

我们可以看到在c++官网是这样定义的
在这里插入图片描述
这个就可以用来在有重叠的空间进行拷贝内容,我们来看看是怎么用的他包含的头文件还是string.h

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

运行结果
在这里插入图片描述
这里我们在同一内存空间成功拷贝了,接下来看看模拟实现

# include<stdio.h>
# include<assert.h>
my_memove(void* start, void* go_to, size_t num)
{void* ret = go_to;assert(start != NULL && go_to != NULL);if(start>go_to){while(num-- != 0){*(char*)go_to = *(char*)start;start = (char*)start + 1;go_to = (char*)go_to + 1;}}else{while (num--){*((char*)go_to + num) = *((char*)start + num);}}return ret;
}
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };my_memove(arr1, arr1+2, 5*sizeof(int));for (int i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}

运行结果
在这里插入图片描述
这里我们需要知道是怎么拷贝的,我们需要分两种情况首先我们是从前往后拷贝,还是从后往前拷贝,通过分析在go_to小于start的时候就从后往前拷贝,当go_to大于start的时候从前往后拷贝这就是这个模拟实现最重要的地方,其他的就好理解了


*((char*)go_to + num) = *((char*)start + num);

这段代码的意思就是从后往前拷贝这里加上一个num就代表来到了这个要拷贝目标的最后一个字节,和要拷贝对象的最后一个字节,这样来实现倒着拷贝。
以上就是对这两个函数的讲解了,如果有什么不足的欢迎指正。

这篇关于内存函数memcpy和memmove的讲解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/821215

相关文章

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N

MySQL中REPLACE函数与语句举例详解

《MySQL中REPLACE函数与语句举例详解》在MySQL中REPLACE函数是一个用于处理字符串的强大工具,它的主要功能是替换字符串中的某些子字符串,:本文主要介绍MySQL中REPLACE函... 目录一、REPLACE()函数语法:参数说明:功能说明:示例:二、REPLACE INTO语句语法:参数

python中update()函数的用法和一些例子

《python中update()函数的用法和一些例子》update()方法是字典对象的方法,用于将一个字典中的键值对更新到另一个字典中,:本文主要介绍python中update()函数的用法和一些... 目录前言用法注意事项示例示例 1: 使用另一个字典来更新示例 2: 使用可迭代对象来更新示例 3: 使用