内存函数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

相关文章

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

C++ vector的常见用法超详细讲解

《C++vector的常见用法超详细讲解》:本文主要介绍C++vector的常见用法,包括C++中vector容器的定义、初始化方法、访问元素、常用函数及其时间复杂度,通过代码介绍的非常详细,... 目录1、vector的定义2、vector常用初始化方法1、使编程用花括号直接赋值2、使用圆括号赋值3、ve

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印