编程之路,从0开始:内存函数

        Hello大家好!很高兴我们又见面了。

       给生活添点passion,开始今天的编程之路!

       今天我们来讲C语言中的内存函数。


目录

1、memcpy内存复制

2、memmove可重叠内存拷贝

3、memset设置字符

4、memcmp比较


 

1、memcpy内存复制

a6bf15c7fc6644ebaae16fc3c7f03501.png

memcpy就是内存复制函数,作用类似于我们的strcpy,但是能实现的功能更多一些。


使用:

#define _CRT_SECURE_NO_WARNINGS 1
#include  <stdio.h>
#include<string.h>
int main()
{char p[5] = "asd";char p1[5] = "***";memcpy(p,p1,2);printf("%s", p);return 0;
}

运行结果:

46c52f4fc3ed4d26b001e0284d121f7a.png

       我们向函数中传入三个参数,前两个为地址,最后一个为复制的字节数。第一个地址为目的地,所以把第二个地址的前两个字节复制到第一个地址的前两个字节处。

memcpy的模拟实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include  <stdio.h>
#include<string.h>
void* My_memcpy(void* a, const void* b, size_t num)
{void* ret = a;while (num){*(char*)a = *(char*)b;(char*)a= (char*)a+1;(char*)b = (char*)b + 1;num--;}
}
int main()
{char p[5] = "asd";char p1[5] = "***";My_memcpy(p,p1,2);printf("%s", p);return 0;
}

       还记得吗void*类型是不能进行函数加减操作的,所以我们要把它转化为(char*)类型,这样才能进行一个字节的前移。


2、memmove可重叠内存拷贝

memmove和memcpy最大区别就是memmove的两个指针可以重叠

6a63d653647747cd808afd6db41be1ef.png

使用:

#define _CRT_SECURE_NO_WARNINGS 1
#include  <stdio.h>
#include<string.h>
int main()
{char p[10] = "aaabbb";memmove(p+3,p,3);printf("%s", p);return 0;
}

运行结果:

d6617129ec8e4f0ba5282bbb9a968860.png

       上面我们把p的前三个字符复制给了后三个字符。有兴趣的试试,这个操作memcpy能不能实现呢?


模拟实现:

        首先我们先分析一下为什么重叠之后memcpy不行:

9445d92d61d44a2aad530074cf40db89.png

       方框为被复制的变量,圆角方框为目的地,现在我们传线路1,然后传线路2,再传线路3,那么这时候问题就来了,线路3的起始地已经被复制为了1,那么这时候我们是想把3复制过去的,这样肯定是达不到我们想要的结果的。

       那么如果这样重叠我们该怎么做呢?我们尝试从后往前复制,这样就不会有问题了:

e834c49ad5b74dbfa4e7a3f7e07532a3.png

同理,如果这样重叠:

45e69332e31e4b7682f6976c48df46a5.png       我们就不能从后往前复制了,只能从前往后复制。

       除了以上两种情况,还有这两种情况,是怎么复制都行的:

4ae3fd145b0f4798b79b489c99d68444.png

bcbef20a5abc4641ae3ddb18287f7e64.png

       那么现在我们是不是可以用if判断是那种情况,把特殊的(可以是从后往前,也可以是从前往后)那一种孤立出来呢?

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include  <stdio.h>
#include<string.h>
void* My_memmove(void* a, const void* b, size_t num)
{void* ret = a;if ((char*)a < (char*)b){while (num){*(char*)a = *(char*)b;(char*)a = (char*)a + 1;(char*)b = (char*)b + 1;num--;}}else{while (num){*((char*)a+num-1) = *((char*)b+num-1);num--;}}
}
int main()
{char p[10] = "aaabbb";My_memmove(p,p+3,3);printf("%s", p);return 0;
}

       我们在这if else分别包含两种情况,这样就把往前复制和往后复制区分开来了。

3、memset设置字符

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

7f6b09edafd84c95b43b61b15fedf3f1.png


函数使用:

#define _CRT_SECURE_NO_WARNINGS 1
#include  <stdio.h>
#include<string.h>
int main()
{char p[10] = "aaabbb";memset(p,'*',3);printf("%s", p);return 0;
}

输出结果:

84bdbc060f6d4e728d6e616ea7c2e2a5.png


模拟实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include  <stdio.h>
#include<string.h>
void My_memcpy(void* a, int b, size_t num)
{while (num){*(char*)a = (char)b;(char*)a= (char*)a+1;num--;}
}
int main()
{char p[5] = "asdf";My_memcpy(p,'*', 2);printf("%s", p);return 0;
}

       在写这里的时候突然想到了一个问题:如果我们写成char p[5]=“asdfg”能不能正常打印呢?

       答案是不行。因为我们在设置字符串是,字符串结尾自带一个‘\0’,他也占了一个字节。

4、memcmp比较

比较两个指针开始,向后的n个字节。

8ee380871dfe436980fd329eeda492bd.png

返回值大于0,则第一个指针指向字符串大,等于0相等,小于0则第二个指针指向字符串大。

7fc8e0f124ca4eb8bfa41c18f66fba00.png


使用:

#include <stdio.h>
#include <string.h>int main()
{char buffer1[] = "asdz";char buffer2[] = "asdfff";int n;n = memcmp(buffer1, buffer2, sizeof(buffer1));if (n > 0) printf("'%s' is greater than '%s'.\n", buffer1, buffer2);else if (n < 0) printf("'%s' is less than '%s'.\n", buffer1, buffer2);else printf("'%s' is the same as '%s'.\n", buffer1, buffer2);return 0;
}

运行结果:

a8d307fbf6bc4500b42ce277d55e917d.png

在这里就不给大家演示memcmp的模拟效果啦~

这里可能有人会说,哎你这博主怎么这样,分享知识怎么都不分享全?

我觉得,学习编程最高效的方式就是上手练习。相信你学到这,已经具备了自己编写模拟memcmp函数的能力了,更何况,memcmp和strcmp又是如此的相似,所以为什么不自己动手试试呢~

好了,今天的知识就分享到这,欢迎订阅我们的专栏:编程之路,后续我会继续更新更多c/c++/算法知识!

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】值传递和地址传递

值传递 引用传递&#xff08;传地址&#xff0c;传引用&#xff09;的区别 传值&#xff0c;是把实参的值赋值给行参 &#xff0c;那么对行参的修改&#xff0c;不会影响实参的值。 传地址&#xff0c;是传值的一种特殊方式&#xff0c;只是他传递的是地址&#xff0c;不是普通…

Springboot采用jasypt加密配置

目录 前言 一、Jasypt简介 二、运用场景 三、整合Jasypt 2.1.环境配置 2.2.添加依赖 2.3.添加Jasypt配置 2.4.编写加/解密工具类 2.5.自定义加密属性前缀和后缀 2.6.防止密码泄露措施 2.61.自定义加密器 2.6.2通过环境变量指定加密盐值 总结 前言 在以往的多数项目中&#xff0…

axios平替!用浏览器自带的fetch处理AJAX(兼容表单/JSON/文件上传)

fetch 是啥&#xff1f; fetch 函数是 JavaScript 中用于发送网络请求的内置 API&#xff0c;可以替代传统的 XMLHttpRequest。它可以发送 HTTP 请求&#xff08;如 GET、POST 等&#xff09;&#xff0c;并返回一个 Promise&#xff0c;从而简化异步操作 基本用法 /* 下面是…

贪吃蛇小游戏设计

贪吃蛇小游戏 1.引言1.1 背景1.2 目的1.3 意义1.4 任务1.5 技术可行性分析1.5.1执行平台1.5.2 语言特性与功能方面 2.需求分析2.1 环境需求2.2开发环境分析2.3游戏功能分析2.4 游戏性能分析2.5 数据流图2.6 数据字典 3.概要设计3.1 设计思路3.2 游戏界面设计3.3 总设计模块的划…

DNS面临的4大类共计11小类安全风险及防御措施

DNS在设计之初&#xff0c;并未考虑网络安全限制&#xff0c;导致了许多问题。DNS安全扩展(DNSSEC)协议的开发旨在解决DNS的安全漏洞&#xff0c;但其部署并不广泛&#xff0c;DNS仍面临各种攻击。接下来我们一起看下DNS都存在哪些安全攻击及缓解措施&#xff0c;旨在对DNS安全…

【大数据学习 | flume】flume的概述与组件的介绍

1. flume概述 Flume是cloudera(CDH版本的hadoop) 开发的一个分布式、可靠、高可用的海量日志收集系统。它将各个服务器中的数据收集起来并送到指定的地方去&#xff0c;比如说送到HDFS、Hbase&#xff0c;简单来说flume就是收集日志的。 Flume两个版本区别&#xff1a; ​ 1&…

Jmeter中的定时器(一)

定时器 1--固定定时器 功能特点 固定延迟&#xff1a;在每个请求之间添加固定的延迟时间。精确控制&#xff1a;可以精确控制请求的发送频率。简单易用&#xff1a;配置简单&#xff0c;易于理解和使用。 配置步骤 添加固定定时器 右键点击需要添加定时器的请求或线程组。选…

区块链技术在慈善捐赠中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 区块链技术在慈善捐赠中的应用 区块链技术在慈善捐赠中的应用 区块链技术在慈善捐赠中的应用 引言 区块链技术概述 定义与原理 发…

[数组二分查找] 0074. 搜索二维矩阵

文章目录 1. 题目链接2. 题目大意3. 示例4. 解题思路5. 参考代码 1. 题目链接 74. 搜索二维矩阵 - 力扣&#xff08;LeetCode&#xff09; 2. 题目大意 描述&#xff1a;给定一个 mn 大小的有序二维矩阵 matrix。矩阵中每行元素从左到右升序排列&#xff0c;每列元素从上到下…

使用 Python 脚本在 Ansys Mechanical 中创建用于后处理的螺栓工具

介绍 由螺栓连接定义的接头在工业应用中非常普遍。在 Ansys Mechanical FEA 中分析它们是一种非常常见的做法。通过Object Generator或Bolt Tools Add-on&#xff0c;使用线体、梁连接甚至3D实体中的梁单元&#xff0c;在Ansys Mechanical中生成螺栓连接非常容易。定义螺栓联接…

【AI声音克隆整合包及教程】第二代GPT-SoVITS V2:创新与应用

一、引言 随着科技的迅猛发展&#xff0c;声音克隆技术已经成为一个炙手可热的研究领域。SoVITS&#xff08;Sound Voice Intelligent Transfer System&#xff09;&#xff0c;作为该领域的先锋&#xff0c;凭借其卓越的性能和广泛的适用性&#xff0c;正在为多个行业带来前所…

python调用MySql详细步骤

一、下载MySql MySQL :: Download MySQL Installerhttps://dev.mysql.com/downloads/windows/installer/8.0.html点击上面链接&#xff0c;进入MySQL8.0的下载页面&#xff0c;选择离线安装包下载。 不需要登陆&#xff0c;直接点击下方的 No thanks,just start my download. …

《InsCode AI IDE:编程新时代的引领者》

《InsCode AI IDE&#xff1a;编程新时代的引领者》 一、InsCode AI IDE 的诞生与亮相二、独特功能与优势&#xff08;一&#xff09;智能编程体验&#xff08;二&#xff09;多语言支持与功能迭代 三、实际应用与案例&#xff08;一&#xff09;游戏开发案例&#xff08;二&am…

华为路由策略配置

一、AS_Path过滤 要求&#xff1a; AR1与AR2、AR2与AR3之间建立EBGP连接 AS10的设备和AS30的设备无法相互通信 1.启动设备 2.配置IP地址 3.配置路由器的EBGP对等体连接&#xff0c;引入直连路由 [AR1]bgp 10 [AR1-bgp]router-id 1.1.1.1 [AR1-bgp]peer 200.1.2.2 as-nu…

如何解决JAVA程序通过obloader并发导数导致系统夯住的问题 | OceanBase 运维实践

案例背景 某保险机构客户的数据中台&#xff0c;自系统上线后不久&#xff0c;会定期的用 obload 工具从上游业务系统导入数据至OceanBase数据库。但&#xff0c;不久便遇到了应用服务器的 Memory 与 CPU 资源占用持续攀升&#xff0c;最终导致系统夯住而不可用的异常。 memo…

【HarmonyOS】鸿蒙系统在租房项目中的项目实战(一)

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…

react17安装html-react-parser运行报错记录

背景 react17 安装 html-react-parser npm install html-react-parser运行终端报错信息 ERROR in ./node_modules/html-react-parser/esm/index.mjs 2:0-122 Cant reexport the named export htmlToDOM from non EcmaScript module (only default export is available)原因…

websocket初始化

websocket初始化 前言 上一集我们HTTP的ping操作就可以跑通了&#xff0c;那么我们还有一个协议---websocket&#xff0c;我们在这一集就要去完成我们websocket的初始化。 分析 我们在初始化websocket的之前&#xff0c;我们考虑一下&#xff0c;我们什么时候就要初始化我们…

JavaEE 重要的API阅读

JavaEE API阅读 目的是为了应对学校考试&#xff0c;主要关注的是类的继承关系、抛出错误的类型、包名、包结构等等知识。此帖用于记录。 PageContext抽象类 包名及继承关系 继承自JspContext类。PageContext 实例提供对与某个 JSP 页⾯关联的所有名称空间的访问&#xff0…

Yocto项目 - VIRTUAL-RUNTIME,它有什么用?

Yocto 项目是一个完整的 Linux 分布构建工具集&#xff0c;提供了构建完全自定义小型核心或完整应用的能力。在这样一个构建系统中&#xff0c;VIRTUAL-RUNTIME这个概念是应用构建和选择处理中的重要部分。这篇文章将从概念、优势、应用场景和实战案例几个方面&#xff0c;全面…