【C语言】内存操作,内存函数篇---memcpy,memmove,memset和memcmp内存函数的使用和模拟实现【图文详解】

欢迎来CILMY23的博客喔,本篇为​【C语言】内存操作,内存函数篇---memcpy,memmove,memset和memcmp内存函数的使用和模拟实现【图文详解】,图文讲解四种内存函数,带大家更深刻理解C语言中内存函数的操作,感谢观看,支持的可以给个一键三连,点赞关注+收藏。 

前言

在结束上一期字符系列篇后,本篇我们将了解四种内存操作的函数,它们分别是memcpy,memmove,memset和memcmp。

目录

一、memcpy

memcpy的介绍和使用 

 memcpy的模拟实现

二、memmove

 memmove的介绍和使用

 memmove的模拟实现

三、memset

四、memcmp 


一、memcpy

 memcpy可以在cplusplus网站查询,memcpy - C++ Reference (cplusplus.com)

函数原型如下:

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

函数介绍如下:

 

函数返回值和使用案例如下:

 

memcpy的介绍和使用 

 memcpy是一个复制内存空间的函数,Copy block of memory,复制内存块,将 num 字节的值从指向的位置直接复制到目标指向的内存块。

那具体是怎么使用的呢?

我们来看一个整型数组的使用案例:

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

结果如下:

 memcpy的模拟实现

思路: 因为我们并不知道要接收什么样的数据类型,所以可以用void *来定义数据类型,因为void*不能直接加减整数,所以我们要将其转换成char * 的一个字节指针变量,然后进行加减,最后赋值给自己。

void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;
}

 写完后,我们看案例,如果目标空间和源空间重叠了呢?

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

结果如下:

我们用自己的拷贝呢?

int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };my_memcpy(arr1+3, arr1, 20);for (int i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}

结果如下: 

 

我们来看过程图:

总结:

1.memcpy的使用需要包括头文件string.h

2.函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
3.memcpy函数在遇到  '\0' 的时候并不会停下来。
4.如果source和destination有任何的重叠,复制的结果都是未定义的。

5.memcpy的返回值是目标空间的起始地址

二、memmove

为了解决上述情况,我们需要用到memmove来解决内存重叠的问题,memmove可以在cplusplus网站查询,memmove - C++ Reference (cplusplus.com)

函数原型如下:

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

函数介绍如下:

函数返回值和使用案例如下:

 memmove的介绍和使用

 memmove可以解决出现内存重叠空间的情况,将 num 字节的值从指向的位置复制到目标指向的内存块。复制就像使用中间缓冲区一样进行,从而允许目标重叠。

int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };memmove(arr1+3, arr1, 20);for (int i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}

结果如下: 

 memmove的模拟实现

 思路:为了解决重叠问题,我们得对src和dest的目标空间起始位置进行讨论,分两种情况,从后往前或者从前往后复制

我们发现当dest在src的右边就需要从后往前拷贝 

 

而dest在src的左边就需要从前往后拷贝 

 

当dest和src不重叠的时候,无论是从前往后,还是从后往前都可以。 

 所以一共有两种方案

方案一,我们采取dest在src前面的情况,然后其余只采用从后往前

方案二、我们采取dest >= src,并且,dest <= (char*)src+ num,

//方案一
void* my_memmove(void* dest, const void* src, size_t num)
{assert(dest && src);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* my_memmove(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;if (dest > src && dest <= (char*)src +num){//从后向前while (num--){*((char*)dest + num) = *((char*)src + num);}}else{//从前向后while (num--){*(char*)dest = *(char*)src;			dest = (char*)dest + 1;src = (char*)src + 1;}}return ret;
}

二者最后的结果如下所示:

总结:
1.如果源空间和⽬标空间出现重叠,就得使用memmove函数处理。

2.memmove的使用需要包括头文件string.h

3.memmove将 num 字节的值将源指向的位置复制到目标指向的内存块。复制就像使用中间缓冲区一样进行,从而允许目标和源空间重叠。

4.memmove和memcpy函数一样在遇到  '\0' 的时候并不会停下来。

5.memmove的返回值是目标空间的起始地址

三、memset

 memset可以在cplusplus网站查询,memset - C++ 参考 (cplusplus.com)

函数原型如下:

void * memset ( void * ptr, int value, size_t num );

函数介绍如下:

 

函数返回值和使用案例如下:

 

函数的使用和介绍 

memset是用来填充内存的,填充内存的值就是函数参数中的value

#include<stdio.h>
#include<string.h>int main()
{char arr[] = "hello CILMY23";memset(arr, '1', 5);for (int i = 0; i < 13; i++){printf("%c ", arr[i]);}return 0;
}

 结果如下:

总结:

1.memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。

2.memset的使用需要包括头文件string.h

3.memset的返回是原空间的地址

4.memset只能对字节进行操作,操作的是一个字节数

四、memcmp 

 memcmp可以在cplusplus网站查询,memcpy - C++ Reference (cplusplus.com)

函数原型如下:

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

函数介绍如下:

函数返回值和使用案例如下:

 memcmp的使用

#include<stdio.h>
#include<string.h>int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 1,5,6,7,8, };int ret = memcmp(arr1, arr2,5);printf("%d ", ret);return 0;
}

总结:

1.memcmp是比较从ptr1和ptr2指针指向的位置开始,向后的num个字节

2.memcmp的使用需要包括头文件string.h

3.memcmp的返回值是ptr1大于ptr2返回大于0的值,小于返回小于0的值,相等返回0

4.memcmp比较的是字节内容

感谢各位同伴的支持,本期内存函数篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2804962.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Seurat包学习:如何查看R包函数源代码

​我们很多时候都很好奇作者的r包是如何写出来的&#xff0c;手痒的时候就想学习一下源码&#xff0c;顺便改一改 问题来源 为什么要写今天这个推文呢&#xff1f; 起因是因为我想使用seurat自带函数画热图&#xff0c;奈何这个图不是那么好看 DoHeatmap(pbmc,features fea…

[HTML]Web前端开发技术28(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;佬佬会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

编译GreatSQL with RocksDB引擎

GreatSQL里也能用上RocksDB引擎 1. 前言 RocksDB 是基于Facebook 开源的一种支持事务的、高度可压缩、高性能的MyRocks存储引擎&#xff0c;特别适用于高度压缩和大容量的数据。以下是一些关键特点&#xff1a; 高性能&#xff1a; LSM 树结构使得RocksDB在写入密集型负载下表现…

2024-02-23 作业

作业要求: 1.自己实现单向循环链表的功能 2.整理思维导图 3.复习前面顺序表和链表的代码&#xff0c;重写链表逆置函数 1.自己实现单向循环链表的功能 运行代码&#xff1a; main.c #include "loop_list.h" int main(int argc, const char *argv[]) {loop_p H cr…

07 STL 简介

目录 什么是STLSTL的版本STL的六大组件STL的重要性如何学习STLSTL的缺陷 1. 什么是STL c标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个包罗数据结构和算法的软件框架 2. STL的版本 原始版本 Alexander Stepanov、Meng Lee在惠普实验室的…

【Python笔记-设计模式】装饰器模式

一、说明 装饰器模式是一种结构型设计模式&#xff0c;旨在动态的给一个对象添加额外的职责。 (一) 解决问题 不改变原有对象结构的情况下&#xff0c;动态地给对象添加新的功能或职责&#xff0c;实现透明地对对象进行功能的扩展。 (二) 使用场景 如果用继承来扩展对象行…

互联网广告投放与IP地理位置定位

随着互联网的发展和普及&#xff0c;互联网广告投放成为各行业推广营销的重要方式之一。而结合IP地理位置定位技术&#xff0c;可以实现精准定向&#xff0c;提高广告投放的效果和精准度。IP数据云将探讨互联网广告投放与IP地理位置定位的关系&#xff0c;分析其优势和应用场景…

Window部署SkyWalking

SkyWalking mysql的驱动依赖 选择下载版本 v9.4 现在后解压缩目录结构 一、修改config目录文件 application.yml 修改1&#xff1a; selector: ${SW_STORAGE:h2} 修改后&#xff1a; selector: ${SW_STORAGE:mysql} 修改2&#xff1a;使用mysql数据库 mysql: properti…

鼠标右键助手专业版 MouseBoost PRO for Mac v3.3.6中文破解

MouseBoost Pro mac版是一款简单实用的鼠标右键助手专业版&#xff0c;MouseBoost Pro for Mac只要轻点你的鼠标右键&#xff0c;就可以激活你想要的各种功能&#xff0c;让你的工作效率大幅度提高&#xff0c;非常好用。 软件下载&#xff1a;MouseBoost PRO for Mac v3.3.6中…

Electron实战之环境搭建

工欲善其事必先利其器&#xff0c;在进行实战开发的时候&#xff0c;我们最终的步骤是搞好一个舒服的开发环境&#xff0c;目前支持 Vue 的 Electron 工程化工具主要有 electron-vue、Vue CLI Plugin Electron Builder、electron-vite。 接下来我们将分别介绍基于 Vue CLI Plu…

【算法与数据结构】417、LeetCode太平洋大西洋水流问题

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;题目要求雨水既能流向太平洋也能流向大西洋的网格。雨水流向取决于网格的高度。一个比较直接的方式是对…

《TCP/IP详解 卷一》第4章 地址解析协议ARP

目录 4.1 引言 4.2 一个例子 4.3 ARP缓存 4.4 ARP帧格式 4.5 ARP例子 4.6 ARP缓存超时 4.7 代理ARP 4.8 免费ARP和地址冲突检测 4.9 ARP命令 4.10 使用ARP设置嵌入式设备IPv4地址 4.11 与ARP相关攻击 4.12 总结 4.1 引言 地址解析&#xff1a; IPv4&#xff1a;AR…

社交媒体变革者:剖析Facebook对在线互动的贡献

随着数字化时代的蓬勃发展&#xff0c;社交媒体已经成为人们日常生活中不可或缺的一部分。在这个领域的发展中&#xff0c;Facebook作为先行者和领导者&#xff0c;对在线互动的演变和发展产生了深远的影响。本文将深入剖析Facebook在社交媒体领域的贡献&#xff0c;以及它对在…

MySql-DQL-条件查询

目录 条件查询修改数据 查询 姓名 为 Name10 的员工查询 id小于等于5 的员工信息查询 没有分配职位 的员工信息查询 有职位 的员工信息查询 密码不等于 password1 的员工信息查询 入职日期 在 2000-01-01 (包含) 到 2010-01-01(包含) 之间的员工信息查询 入职时间 在 2000-01-0…

跨区互联组网怎么做?SD-WAN专线可以实现吗?

在当今数字化时代&#xff0c;企业不断扩张&#xff0c;跨区域互联成为业务发展的必然需求。然而&#xff0c;跨区互联组网涉及到复杂的网络架构和连接&#xff0c;传统的网络方案往往难以满足高性能、高可靠性和低成本的要求。SD-WAN专线技术的出现&#xff0c;为跨区互联组网…

C++:Level2阶段测试

总结。 只要你看过我的文章&#xff0c;哪怕只是一半&#xff0c;一定能够过关&#xff01; 准备好开始测试氻吗&#xff1f; 判断题&#xff0c;每题4分&#xff0c;共100分 1、Red Panda Dev C Maker【3.0自创黑客版】添加的头文件有Heike.h&#xff08;&#xff09; 2、在…

Java 学习和实践笔记(19):this的使用方法

this用来指向当前对象的地址。 this的用法&#xff1a; 1&#xff09;在普通方法中&#xff0c;this总是指向调用该方法的对象。在普通方法中&#xff0c;它是作为一种隐式参数一直就存在着&#xff08;这句话的意思&#xff0c;就是其实在普通方法中&#xff0c;编译器一直就…

go使用trpc案例

1.go下载trpc go install trpc.group/trpc-go/trpc-cmdline/trpclatest 有报错的话尝试配置一些代理&#xff08;选一个&#xff09; go env -w GOPROXYhttps://goproxy.cn,direct go env -w GOPROXYhttps://goproxy.io,direct go env -w GOPROXYhttps://goproxy.baidu.com/…

Django学习笔记-forms使用

1.创建forms.py文件,导入包 from django import forms from django.forms import fields from django.forms import widgets2. 创建EmployeeForm,继承forms.Form 3.创建testform.html文件 4.urls.py添加路由 5.views中导入forms 创建testform,编写代码 1).如果请求方式为GET,…

go 1.18 不同目录package引用问题

go 1.18开始使用module了 不同的package在vs code中引用的话 需要先开启 是Go1.11版本之后 推出的版本管理工具 有点类似java的 maven工具 可以引入依赖使用 go env -w GO111MODULEon 先把这个打开 然后在创建的vs code工作目录下 执行 module gomdoule module 模块名 会生…