【C语言】_内存拷贝函数memcpy与memmove

ops/2025/1/21 10:07:05/

目录

1. memcpy

1.1 函数声明及功能

1.2 使用示例

1.3 模拟实现

2. memmove

2.1 函数声明与功能

2.2 使用示例

2.3 模拟实现


1. memcpy

在专栏前文已介绍字符串拷贝函数strcpy,但其仅能实现字符串的拷贝。若需对其他类型如整型、浮点型、结构体等变量进行拷贝,则无法再使用strcpy实现。

memcpy函数针对内存块实现拷贝;

1.1 函数声明及功能

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

memcpy函数功能:

将source位置开始向后num个字节的数据复制到destination指向的内存位置

返回值为拷贝的目标空间的起始地址;

注:1、memcpy在遇到\0时并不会停止;

2、如果source和destination有任何重叠,memcpu的行为是未定义的,可能导致数据损坏

3、memcpy虽然为内存拷贝函数,但使用时所需包含的头文件为string.h

1.2 使用示例

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

运行结果如下:

 

1.3 模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, size_t num) {assert(dest && src);int i = 0;void* ret = dest;// num单位为字节(而非元素)while (num--) {// 逐字节拷贝*((char*)dest) = *((char*)src);src = (char*)src + 1;dest = (char*)dest + 1;}// 返回拷贝的目标空间的起始地址return ret;
}
int main() {int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] = { 0 };memcpy(arr2, arr1,7*4);for (int i =0; i < 20; i++) {printf("%d ", arr2[i]);}return 0;
}

注:对于src = (char*)src + 1,不可写为src++,src为void*类型,不可直接进行加减运算;

但可写为((char*)src)++,表示强转为char*类型后再自增;

2. memmove

对于memcpy,它只负责不重叠空间的内存拷贝工作,在注2中已经提到;

若需实现拷贝的源和目标内存区域有重合部分的内容拷贝,则需使用memmove函数

2.1 函数声明与功能

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

注:对于调用者,相较于memcpy,memmove并未增加额外的参数。其可以实现重叠内存区域的拷贝的逻辑,在模拟实现部分进行说明;

2.2 使用示例

#include<stdio.h>
#include<string.h>
int main() {int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };// 将1、2、3、4、5拷贝至3、4、5、6、7位置处memmove(arr1 + 2, arr1, 5 *sizeof(int));for (int i = 0; i < 10; i++) {printf("%d ", arr1[i]);}return 0;
}

运行结果如下:

 

2.3 模拟实现

memmove可以处理源内存区域和目标区域有重叠的情况,模式实现具体实现逻辑有两种:

(1)额外再开辟一个数组作为临时缓冲区,先将源内存区域的数据复制到一个临时缓冲区,再从临时缓冲区复制到目标内存区域,确保数据不会被覆盖;(两次拷贝实现,此处不再)

(2)分情况从前向后或从后向前依次将源内存空间数据拷贝至目标内存空间:

情况1:

 情况2:

情况3:

现将情况2与3合并,故对src与dest分段如下:

当dest落在src之前时,从前向后依次拷贝;

当dest落在src之后时,从后向前依次拷贝;

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* dest, const void* src, size_t num) {assert(src && dest);void* ret = dest;if (dest < src) {// 从前向后依次拷贝while (num--) {*((char*)dest) = *((char*)src);dest = (char*)dest + 1;src = (char*)src + 1;}}else {// 从后向前依次拷贝while (num--) {*((char*)dest + num) = *((char*)src + num);}}// 返回目标空间的起始地址return ret;
}
void PrintInt(int* arr, int sz) {for (int i = 0; i < sz; i++) {printf("%d ", *(arr + i));}printf("\n");
}
int main() {int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int sz = sizeof(arr1) / sizeof(arr1[0]);// 将1、2、3、4、5拷贝至3、4、5、6、7位置处my_memmove(arr1 + 2, arr1, 5 * sizeof(int));PrintInt(arr1, sz);int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };// 将3、4、5、6、7拷贝至1、2、3、4、5位置处my_memmove(arr2, arr2 + 2, 5 * sizeof(int));PrintInt(arr2, sz);return 0;
}

测试用例运行结果如下:


http://www.ppmy.cn/ops/151880.html

相关文章

Java 数组排序

目录 1.Java冒泡排序&#xff08;Bubble Sort&#xff09; 1.冒泡排序 2.冒泡排序的算法原理 3.冒泡排序的复杂度和性能 4.形成代码 2.Java快速排序&#xff08;Quick Sort&#xff09; 3.Java归并排序&#xff08;Merge Sort&#xff09; 4.Java选择排序&#xff08;S…

数据库性能优化(sql优化)_SQL执行计划01_yxy

数据库性能优化_SQL执行计划详解01 1 执行计划简介1.1 什么是sql执行计划?1.2 执行计划解决了什么问题?1.3 总结2 执行计划的查看方式3 执行计划完整示例4 执行计划组成部份1 执行计划简介 1.1 什么是sql执行计划? 执行计划(Execution Plan),也称为查询计划或解释计划,…

主从设备的同步(基于binlog和gtid实现同步)

一、原理 1、MySQL将数据变化记录到二进制日志中&#xff1b; 2、Slave将MySQL的二进制日志拷贝到Slave的中继日志中&#xff1b; 3、Slave将中继日志中的事件在做一次&#xff0c;将数据变化&#xff0c;反应到自身&#xff08;Slave&#xff09;的数据库 以便&#xff1a; 灾…

Jetbrains 官方微信小程序插件已上线!

就在昨天&#xff0c;Jetbrains官方发布了一篇文章&#xff0c;宣布它们发布了一款专用于微信小程序开发的插件&#xff08;插件名称&#xff1a;WeChat Mini Program&#xff09;&#xff0c;至此&#xff0c;大家可以使用Jetbrains家的IDE&#xff08;例如IDEA、WebStorm&…

Arm 计划涨价高达 300%,并考虑自行研发芯片

Arm 计划涨价高达 300% 据财联社 1 月 14 日消息&#xff0c;芯片技术供应商 Arm Holdings&#xff08;Arm&#xff09;正在制定一项长期战略&#xff0c;计划将其芯片设计授权费用提高高达 300%&#xff0c;并考虑自主研发芯片&#xff0c;以与其最大的客户展开竞争。以下是详…

OpenCV的TIF红外可见光融合算法

一、简介 首先TIF是Two-Scale Image Fusion的缩写&#xff0c;论文《Two-Scale Image Fusion of Infrared and Visible Images Using Saliency Detection (TIF)》&#xff0c;作者在论文中提到TIF算法主要通过以下三个步骤实现融合&#xff1a; 图像分解&#xff0c;图像分解使…

基于Python招聘职位数据采集与数据可视化分析

摘要 随着互联网技术的发展&#xff0c;网络招聘成为招聘者与求职者的主要选择&#xff0c;许多大型招聘网站也随之出现&#xff0c;越来越多的毕业生和求职者造成了社会就业压力巨大的现状。因此设计并实现招聘职位数据采集与数据可视化分析系统有重要的研究价值和意义。该系统…

风吹字符起,诗意Linux:一场指令与自由的浪漫邂逅(上)

文章目录 前言一. 知识过渡文件的属性与类型路径 二. 基本指令ls&#xff1a;风起草长&#xff0c;窥见世界的全貌cd&#xff1a;穿梭路径间&#xff0c;漫步荒原的远方pwd&#xff1a;定位自我&#xff0c;荒原上的坐标mkdir&#xff1a;种下希望&#xff0c;创建属于自己的世…