当前位置: 首页 > news >正文

【C语言进阶】内存函数

天生我材必有用,千金散尽还复来。                                  ——李白

 

目录

前言

一.memcpy函数

​1.实现memcpy函数

2.模拟实现memcpy函数

二.memmove函数

1.实现memmove函数

2.模拟实现memmove函数 

三.memcpy函数和memmove函数的关系 

四.memcmp函数

1.实现memcmp函数

2.模拟实现memcmp函数 

五.memset函数 


前言

上次我们学习了字符串函数:strcpy,strcat,strcmp等等字符串函数,顾名思义这些字符串函数只能对字符串进行一系列的操作,而不能对整型,浮点型之类的内容进行操作。

今天我们就要学习内存函数:memcpy,memmove,memcmp等等内存函数。前缀mem就是英文里面的memory单词的意思,而memory在计算机里面理解为内存,所以这些函数是对内存进行操作,不会被类型所限制,可以操作各种各样的类型。

一.memcpy函数

 void *memcpy( void *dest, const void *src, size_t count ),这里为什么要用void*的指针呢?

因为这是一个内存函数,我们可以操作各种的数据类型,void*的指针可以接收任何类型的指针。在要使用的时候,只需要将void*强制类型转换即可达到目的。

 1.实现memcpy函数

#include<stdio.h>
#include<string.h>//内存函数的头文件
int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };memcpy(arr2, arr1, 20);//20也就是20个字节,即拷贝5个整型int i = 0;for (i = 0; i < 5; i++){printf("%d ", arr2[i]);}return 0;
}

2.模拟实现memcpy函数

void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);void* start = dest;while (num)//一共20个字节{*(char*)dest = *(char*)src;//一个一个字节的进行拷贝dest = (char*)dest + 1;src = (char*)src + 1;num--;//直到num为0个字节时,即拷贝结束}return start;
}
int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };my_memcpy(arr2, arr1, 20);//20也就是20个字节,即拷贝5个整型int i = 0;for (i = 0; i < 5; i++){printf("%d ", arr2[i]);}return 0;
}


 

当我们要把自己数组的内容给拷贝的自己的数组内容上会发生什么?

void* my_memcpy(void* dest, const void* src, size_t num)
{assert(dest && src);void* start = dest;while (num)//一共20个字节{*(char*)dest = *(char*)src;//一个一个字节的进行拷贝dest = (char*)dest + 1;src = (char*)src + 1;num--;//直到num为0个字节时,即拷贝结束}return start;
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };my_memcpy(arr+2, arr, 20);//在一个数组里面操作int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

我们的目的是arr数组里面的3 4 5 6 7改为1 2 3 4 5,结果应该是1 2 1 2 3 4 5 8 9 10。结果是什么呢?让我们一起来看看。

结果为什么是这样呢?我们不妨通过画图来理解一下,在做题时,画图时非常重要的。 

这里就是有重叠的部分,在对于有重叠的部分 ,我们使用memmove函数。

二.memmove函数

1.实现memmove函数

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

2.模拟实现memmove函数 

void* my_memmove(void* dest, void* src, size_t num)
{assert(dest && src);void* start = dest;while (num){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;num--;}return start;
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr+2, arr, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

为什么又是这样,到这里可能人都要被气成sb,但是我们要心平气和,继续我们的画图来好好的来理解一下。

 

正确的代码: 

void* my_memmove(void* dest, void* src, size_t num)
{assert(dest && src);void* start = dest;if(dest>src){while (num--){*((char*)dest + num) = *((char*)src + num);}}else{while (num){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;num--;}}return start;
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr+2, arr, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

三.memcpy函数和memmove函数的关系 

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

这里可以看出数组即使有重叠的部分 ,但是memcpy函数一样的可以实现和memmove函数一样的功能。我们可以这样理解:其实memcpy函数是memmove函数的一个子函数。

在vs平台上memcpy函数和memmove的功能一模一样,但是并不保证在其他平台上面两个函数的功能是一样的。

总结:在有重叠部分的时候都用memmove函数。没重叠部分的,两个函数用谁都行。

四.memcmp函数

1.实现memcmp函数

memcmp函数也是一个字节一个字节的进行比较。同样和strcmp函数一样,最后比较的是ASCll码值。

int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 1,2,3,4,5,7 };int ret=memcmp(arr1, arr2, 20);printf("%d\n", ret);return 0;
}


 

比较21字节会是怎么样呢? 

int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 1,2,3,4,5,7 };int ret=memcmp(arr1, arr2, 21);//比较21字节会是怎么样呢?//前20个字节都相等,这是毋庸置疑的的//6的小端字节序:06 00 00 00//7的小端字节序:07 00 00 00//很明显7的第一个字节大于6,即arr2大于arr1,返回-1printf("%d\n", ret);return 0;
}


 

2.模拟实现memcmp函数 

模拟实现memcmp函数和模拟实现strcmp函数是非常相似的。

int my_memcmp(const void* buf1, const void* buf2, size_t num)
{assert(buf1 && buf2);size_t m = num;while (num--){if (*(char*)buf1 == *((char*)buf2)){buf1 = (char*)buf1 + 1;buf2 = (char*)buf2 + 1;}elsereturn (*(char*)buf1 - *((char*)buf2));}return 0;//退出循环都没有return,那么就说明两个是相等的。
}
int main()
{int arr1[10] = { 1,2,4,4,5,6,7,8,9,10 };int arr2[10] = { 1,2,5 };int ret = my_memcmp(arr1, arr2, 9);//比较9个字节if (ret == -1){printf("arr1小于arr2\n");}else if (ret == 1){printf("arr1大于arr2\n");}elseprintf("arr1和arr2相等\n");return 0;
}

五.memset函数 

void *memset(void *str, int c, size_t n)
//str -- 指向要填充的内存块。
//c -- 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
//n -- 要被设置为该值的字符数。

代码实现:

int main()
{char arr[20] = "hello world";memset(arr, '*', 5);//将arr的前五个字节改为*printf("%s\n", arr);
}


 

如果我们要对整数进行操作呢?

int main()
{int arr[10] = { 1,2,3,4,5 };memset(arr, 1, 8);//操作8个字节int i = 0;for (i = 0; i < 5; i++){printf("%d ", arr[i]);}return 0;
}

这里为什么为得到这么奇怪的数字呢?

注意:memset是一个一个字节的进行操作,而int是4个字节为一个数字。 

如:1的小端字节序是 01 00 00 00,然后一个一个字节的改为1,最后就成了 01 01 01 01

16进制的01010101就是16843009。

所以memset不能随便用,有可能会带来不一样的结果。要根据实际情况来使用。

感谢老铁们的支持。 

相关文章:

【C语言进阶】内存函数

天生我材必有用&#xff0c;千金散尽还复来。 ——李白 目录 前言 一.memcpy函数 ​1.实现memcpy函数 2.模拟实现memcpy函数 二.memmove函数 1.实现memmove函数 2.模拟实现memmove函数 三.memcpy函数和memmove函数的关系 四.memcm…...

Java开发 - ELK初体验

前言 前面我们讲过消息队列&#xff0c;曾提到消息队列也具有保存消息日志的能力&#xff0c;今天要说的EL看也具备这个能力&#xff0c;不过还是要区分一下功能的。消息队列的日志主要指的是Redis的AOF&#xff0c;实际上只是可以利用了消息队列来保存&#xff0c;却并不是消…...

AI_Papers周刊:第六期

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 2023.03.13—2023.03.19 文摘词云 Top Papers Subjects: cs.CL 1.UPRISE: Universal Prompt Retrieval for Improving Zero-Shot Evaluation 标题&#xff1a;UPRISE&#xff1a;改进零样本评估…...

JS运行环境、包管理、打包工具总结

&#x1f333;JS运行环境-node.js 运行环境就是代码解析和执行的程序&#xff0c;比如jvm等虚拟机&#xff0c;他们的主要工作就是根据设定的语法规则解析编译代码&#xff0c;然后运行代码。 js的语法规则遵循ES规范。 &#x1f341;node.js Node.Js官网 Node.js是一种基于Ch…...

day4网络编程(广播和组播)

1.广播 发送端&#xff08;类似于客户端&#xff09; 流程&#xff1a; 创建套接字 填充接收端&#xff08;服务器&#xff09;网络信息结构体 bind(非必须绑定) 设置允许广播 向接收端&#xff08;服务器&#xff09;发送数据 关闭套接字文件 #include <stdio.h> #in…...

Vue3 自动引入组件及函数、动态生成侧边栏路由

Vue3 自动引入组件及函数、动态生成侧边栏路由 1、安装依赖 npm install -D unplugin-auto-import unplugin-icons unplugin-vue-components插件使用说明 unplugin-auto-import 说明 —— 自动引入函数、组件 unplugin-vue-components 说明 —— 自动注册组件 unplugin-ic…...

人工智能交互系统界面设计

文章目录前言一、项目介绍二、项目准备三、项目实施1.导入相关库文件2.人脸信息验证功能3.语音交互与TCP数据通信4.数据信息可视化四、相关附件前言 在现代信息化时代&#xff0c;图形化用户界面&#xff08;Graphical User Interface, GUI&#xff09;已经成为各种软件应用和…...

蓝桥杯嵌入式第一课--创建工程

概述学习本节之前&#xff0c;必须要先安装好 keil5 以及 CubeMX 等软硬件环境&#xff0c;如果你已经安装完成&#xff0c;请告诉自己&#xff1a;考试现在开始&#xff01;从CubeMX开始CubeMX是创建工程模板的软件&#xff0c;也是我们比赛时第一个要进行操作的软件。一、选择…...

Java面向对象:接口的学习

本文介绍了Java中接口的基本语法, 什么是接口, java中的接口 语法规则, 接口的使用,接口的特性,如何实现多个接口,接口间的继承,以及抽象类和接口的区别 Java接口的学习一.接口的概念二.Java中的接口1.接口语法规则2.接口的使用3.接口的特性4.实现多个接口5.接口间的继承三.抽象…...

西瓜视频登录页面

题目 代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>登录页面</title><style>td{width: 160px;height: 25px;}img{width: 20px;height: 20px;}.number, .password{background: rgba(0,0,0,.05);}.numbe…...

【springboot】常用快捷键:

Ctrl快捷键介绍Ctrl F在当前文件进行文本查找 &#xff08;必备&#xff09;Ctrl R在当前文件进行文本替换 &#xff08;必备&#xff09;Ctrl Z撤销 &#xff08;必备&#xff09;Ctrl Y删除光标所在行 或 删除选中的行 &#xff08;必备&#xff09;Ctrl X剪切光标所在行…...

宝塔控制面板常用Linux命令大全

宝塔面板是站长朋友们常见的一款服务器运维面板&#xff0c;可以通过 Web 端轻松管理服务器&#xff0c;提升运维效率。大家在服务器中安装宝塔面板会用到宝塔面板特定的脚本命令。今天这篇文章为大家整理汇总了宝塔面板常用Linux命令&#xff0c;这样方便大家收藏查找。 1、安…...

C语言实现单链表(超多配图,这下不得不学会单链表了)

目录 一&#xff1a;什么是链表&#xff1f; 二&#xff1a;创建源文件和头文件 (1)头文件 (2)源文件 三&#xff1a;实参和形参 四&#xff1a;一步步实现单向链表 &#xff08;1&#xff09;建立一个头指针并置空 &#xff08;2&#xff09;打印链表&#xff0c;便于…...

SQL编写优化技巧

一、底层原理 sql慢是因为没有走索引&#xff0c;因此需要添加索引然它走索引联合索引需要匹配最左匹配原则&#xff08;索引回表&#xff09;如果查询列超出索引的key&#xff0c; 会导致回表&#xff0c;回表数量多&#xff0c;则会走全表扫描 索引是分聚集索引、非聚集索引…...

【基础算法】单链表的OJ练习(6) # 复制带随机指针的链表 #

文章目录&#x1f347;前言&#x1f34e;复制带随机指针的链表&#x1f351;写在最后&#x1f347;前言 本章的链表OJ练习&#xff0c;是最后的也是最难的。对于本题&#xff0c;我们不仅要学会解题的思路&#xff0c;还要能够通过这个思路正确的写出代码&#xff0c;也就是思路…...

Activity生命周期完成EvenetLog回调

Activity 生命周期 系统EvenetLog回调 EventLog路径: Android13/frameworks/base/core/java/android/app/EventLogTags.logtags wm_on_create_called wm_on_restart_called wm_on_start_called wm_on_resume_called wm_on_top_resumed_gained_called wm_on_top_resumed_lost_c…...

西安石油大学C语言期末真题实战

很简单的一道程序阅读题&#xff0c;pa’默认为a【0】&#xff0c;接下来会进行3次循环 0 1 2 输出结果即可 前3题就是一些基础定义&#xff0c;在此不多赘述 要注意不同的数据类型的字节数不同 a<<2 b>>1&#xff08;b>>1;就是说b自身右位移一位&#xff08…...

【Shell】Shell变量

Shell变量系统预定义变量自定义变量基本语法定义变量撤销变量命名规则使用变量只读变量删除变量变量类型系统预定义变量 $HOME、$PWD、$SHELL、$SUSER等 实例 yysubuntu:~$ echo $HOME #查看系统变量的值 /home/yys yysubuntu:~$ set #显示当前shell中所有变量自定义变量…...

你是真的“C”——结构体中鲜有人知的“秘密”

你是真的“C”——结构体中的精髓剖析【内存对齐】 【位段】 &#x1f60e;前言&#x1f64c;结构体内存对齐&#xff1a;&#x1f60a;结构体内存对齐存在的意思是什么&#xff1f;&#x1f618;内存对齐例子详细剖析&#xff1a;&#x1f618;结构体中的位段&#xff1a;&…...

2023年“网络安全”赛项江苏省淮安市赛题解析(超详细)

2023年中职组江苏省淮安市“网络空间安全”赛项 ①.2023年中职组江苏省淮安市任务书②.2023年中职组江苏省淮安市解析③.需要环境或者不懂的可以私信博主!①.2023年中职组江苏省淮安市任务书 任务一:服务器内部信息获取 任务环境说明: 服务器场景:Server210510(关闭链接…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...