搞懂内存函数

引言

本文介绍memcpy的使用和模拟实现、memmove的使用和模拟实现、memcmp使用、memset使用

 158c3f50b199454985017a51dbef9841.png               ✨ 猪巴戒:个人主页✨

               所属专栏:《C语言进阶》

        🎈跟着猪巴戒,一起学习C语言🎈

目录

引言

memcpy

memcpy的使用

memcpy的模拟实现

memmove

memcpy函数不用来处理重叠的内存的数据拷贝:

memmove的模拟实现

 总结:

 模拟实现代码

memcmp

memset


memcpy

void * memcpy ( void * destination, const void * source, size_t num )
  • memcpy的作用就是将source的内容拷贝到destination
  • num说明了拷贝多少个字节
  • 返回值是destination.

memcpy的使用

#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, 20);int i = 0;for (i = 0; i < 5; i++){printf("%d ", arr2[i]);}return 0;
}

5832dc2659294508bad478215341d1aa.png


memcpy的模拟实现

 内存函数就是无论是什么类型的数据都可以使用。

void* ,属于通用类型的指针,可以存放任意类型的地址。

assert,断言,保证dest和source不是空指针。

num是需要拷贝的字节数。

通过将地址转化为(char*)的形式,将需要拷贝的内容一个字节一个字节地将它们拷贝,就可以实现各种数据的拷贝。

然后dest转移到下一个字节,source转移到下一个字节,知道拷贝完num个字节算结束。

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* source, size_t num)
{assert(dest && source);void* start = dest;while (num--){*(char*)dest = *(char*) source;dest = (char*)dest + 1;source = (char*)source + 1;}return start;
}


memmove

void * memmove ( void * destination, const void * source, size_t num )
  • 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
  • 参数和memcpy是一样的。 

memcpy函数不用来处理重叠的内存的数据拷贝:

将arr1数组改成{1,2,1,2,3,4,5,8,9,10},从第三位元素开始,拷贝自己的第一到第五个元素

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* source, size_t num)
{assert(dest && source);void* start = dest;while (num--){*(char*)dest = *(char*) source;dest = (char*)dest + 1;source = (char*)source + 1;}return start;
}
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };my_memcpy(arr1 + 2, arr1, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}

70351ed1ff4a4ba599115e7b0678b91b.png

memcpy在重叠内存拷贝的时候,第三个元素被改成1,第四个元素被改成2,

而第五个元素本来是应该赋值为3的,但是第三个元素已经被改成1了。

第六个元素本来是由第四个元素重新赋值,但是第四个元素被改成了2.

39380881c7a64356adb8af265f088548.png

memmove的模拟实现

如果说我们要将红色部分拷贝到蓝色部分

从前向后拷贝不行,我们要将红色的部分拷贝到蓝色的部分,先将第一个元素拷贝到第三个元素,红色区域的内存被改变,等到将第三个元素拷贝到第五个元素的时候,第三个元素已经发生改变。

从后向前拷贝,如果我们可以先将第五个元素拷贝到第七个元素,这样红色的三、四、五元素先拷贝完后被改变就可以把数值3,4,5成功传到第五、六、七个元素。

25c5324f1eb04ea586499ddf3238b85c.png

 这一次,

从后向前拷贝不行,我们要将红色部分拷贝到蓝色的部分,先将第七个元素拷贝到第五个元素,首先改变了第五个元素的内容,到时候第五个元素还要对第三个元素进行拷贝。

从前向后拷贝,如果我们先将第三个元素拷贝到第一个元素,等轮到第三个元素进行拷贝的时候,第三个元素里的内容已经转出去了,转到第一个元素了,那么第三个元素的内容就可以随便修改了。

ce3a5a681399471bb10ed37671736832.png

 总结:

为了保证source中的数据在拷贝之前就被修改,

  • 当dest在source的右边的时候,采用从后向前的方式
  • 当dest在source的左边的时候,采用从前向后的方式

 模拟实现代码

#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* source, size_t num)
{assert(dest && source);void* start = dest;if (dest < source){//从前向后while (num--){*(char*)dest = *(char*)source;dest = (char*)dest + 1;source = (char*)source + 1;}}else{//从后向前拷贝while (num--){*((char*)dest + num) = *((char*)source + num);}}return start;
}

memcmp

可以比较任意类型的数据

int memcmp ( const void * ptr1, const void * ptr2, size_t num )
  • ptr1指向的第一个空间
  • ptr2指向的第二块空间
  • ptr1和ptr2之间的内存比较
  • num表示需要比较的字节大小

63c51fcf34ab485697e73736e1b3cf45.png


 arr1和arr2比较,arr1比arr2小,返回小于0的数值。

int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 1,3,2 };int ret = memcmp(arr1, arr2, 12);printf("%d", ret);return 0;
}

7da67d9fc3684a7ab9f8ec3fd30040bb.png​ 


memset

void * memset ( void * ptr, int value, size_t num )
  • ptr需要填充的地址空间
  • value,填充什么字符
  • num,填充几个字节
#include<stdio.h>
#include<string.h>
int main()
{char arr[] = "hello world";memset(arr, 'x', 5);printf("%s\n", arr);return 0;
}

92ad5e3e260e4e8988224f64fb739406.png

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

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

相关文章

JS加密/解密之HOOK实战2

上一篇文章介绍了HOOK常规的应用场景&#xff0c;这篇我们讲一下HOOK其他原生函数。又是一个新的其他思路 很多时候&#xff0c;当我们想要某些网站的请求参数的时候&#xff0c;因为某些加密导致了获取起来很复杂。 这时候hook就十分方便了 源代码 var _JSON_Parse JSON.…

scp 指令详细介绍

目录 1. 基本语法 2. 例子 从本地到远程 从远程到本地 从远程到远程 使用端口和指定私钥 递归复制目录 3. 注意事项 如何拷贝文件的软链接 SCP&#xff08;Secure Copy Protocol&#xff09;是一种用于在计算机之间安全地传输文件的协议。它通过加密的方式在网络上安全…

Vue:Vue的开发者工具不显示Vue实例中的data数据

一、情况描述 代码&#xff1a; 页面&#xff1a; 可以看到&#xff0c;input获取到了data数据&#xff0c;但是&#xff0c;vue-devtool没有获取到data数据 二、解决办法 解决办法1&#xff1a; data.name的值不能全是中文&#xff0c;比如改成aa尚硅谷 解决办法2&…

C语言 编程题

C语言学习&#xff01; 1.小明上课需要走n阶台阶&#xff0c;他每次可以选择走一阶或者走两阶&#xff0c;他一共有多少种走法&#xff1f; 输入描述&#xff1a;输入包含一个整数n&#xff08;1 ≤ n ≤30&#xff09; 输出描述&#xff1a;输出一个整数&#xff0c;即小明可…

LeetCode 1457. 二叉树中的伪回文路径||位运算 DFS

1457. 二叉树中的伪回文路径 给你一棵二叉树&#xff0c;每个节点的值为 1 到 9 。我们称二叉树中的一条路径是 「伪回文」的&#xff0c;当它满足&#xff1a;路径经过的所有节点值的排列中&#xff0c;存在一个回文序列。 请你返回从根到叶子节点的所有路径中 伪回文 路径的…

Golang优雅实现按比例切分流量

我们在进行灰度发布时&#xff0c;往往需要转发一部分流量到新上线的服务上&#xff0c;进行小规模的验证&#xff0c;随着功能的不断完善&#xff0c;我们也会逐渐增加转发的流量&#xff0c;这就需要按比例去切分流量&#xff0c;那么如何实现流量切分呢&#xff1f; 我们很容…

力扣(LeetCode)-1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回…

【交流】PHP生成唯一邀请码

目录 前言&#xff1a; 1.随机生成&#xff0c;核对user表是否已存在 代码&#xff1a; 解析&#xff1a; 缺点&#xff1a; 2.建表建库&#xff0c;每次从表中随机抽取一条&#xff0c;用完时扩充 表结构 表视图 代码 解析 缺点 结论&#xff1a; 前言&#xff1a; …

LinuxBasicsForHackers笔记 -- 压缩和归档

压缩分为有损或无损。有损压缩对于减小文件大小非常有效&#xff0c;但会丢失信息的完整性。换句话说&#xff0c;压缩后的文件与原始文件并不完全相同。 这种类型的压缩非常适合图形、视频和音频文件&#xff0c;文件中的微小差异几乎不会被注意到。 本章重点介绍这种无损压缩…

解读Stable Video Diffusion:详细解读视频生成任务中的数据清理技术

Diffusion Models视频生成-博客汇总 前言:Stable Video Diffusion已经开源一周多了,技术报告《Stable Video Diffusion: Scaling Latent Video Diffusion Models to Large Datasets》对数据清洗的部分描述非常详细,虽然没有开源源代码,但是博主正在尝试复现其中的操作。这篇…

医学影像PACS信息化数字平台源码

PACS系统对医院影像科意义重大&#xff0c;将业务量巨大的影像检验流程依托于信息化技术&#xff0c;对于进行信息化建设的医院而言&#xff0c;是十分必要的。 PACS系统源码&#xff0c;集成三维影像后处理功能&#xff0c;包括三维多平面重建、三维容积重建、三维表面重建、三…

包装类, 泛型---java

目录 一. 包装类 1.1 基本数据类型和对应的包装类 1.2 装箱和拆箱 二. 泛型 2.1什么是泛型 2.2泛型的引入 2.3 泛型类语法 2.4 泛型类的使用 2.5 裸类型(Raw Type)(了解) 2.6 泛型是如何编译的 2.7 泛型的上界 2.8 泛型方法 一. 包装类 在 Java 中&#xff0c;由于基本…

uniapp实战 —— 竖排多级分类展示

效果预览 完整范例代码 页面 src\pages\category\category.vue <script setup lang"ts"> import { getCategoryTopAPI } from /apis/category import type { CategoryTopItem } from /types/category import { onLoad } from dcloudio/uni-app import { compu…

vue指令

v-text 更新元素的 textContent。如果要更新部分的 textContent&#xff0c;需要使用 {{ Mustache }} 插值。 <span v-text"msg"></span> <!-- 和下面的一样 --> <span>{{msg}}</span>v-html 更新元素的 innerHTML。注意&#xff1a;内…

基于高通MSM8953平台android9.0的GPIO驱动开发

2.1、注册设备&#xff1a; 2.1.1、添加编译选项&#xff1a; 1&#xff09;、修改kernel/msm-4.9/drivers/leds下Makefile文件&#xff1a; obj-$(CONFIG_LED_GPIO) led_gpio.o 2&#xff09;、修改kernel/msm-4.9/drivers/leds下Kconfig文件&#xff1a; config LED_GPIO…

Java实现归并排序算法

归并排序算法 &#xff08;1&#xff09;基本思想&#xff1a;归并&#xff08;Merge&#xff09;排序法是将两个&#xff08;或两个以上&#xff09;有序表合并成一个新的有序表&#xff0c;即把待排序序列分为若干个子序列&#xff0c;每个子序列是有序的。然后再把有序子序…

蛋白质序列FeatureDict转化为TensorDict

主要转化语句为 tensor_dict {k: tf.constant(v) for k, v in np_example.items() if k in features_metadata}。 增加了特征名称的选择&#xff0c;不同特征维度&#xff0c;特征数的判断等。 from typing import Dict, Tuple, Sequence, Union, Mapping, Optional #import …

postgresql_conf中常用配置项

在 PostgreSQL 的 postgresql.conf 配置文件中&#xff0c;有许多常用的配置项&#xff0c;这些配置项可以根据特定需求和性能优化进行调整。以下是一些常用的配置项及其作用&#xff1a; 1. shared_buffers 用于设置 PostgreSQL 实例使用的共享内存缓冲区大小。增加此值可以…

游戏被攻击该怎么办?游戏盾该如何使用,游戏盾如何防护攻击

随着Internet互联网络带宽的增加和多种DDOS黑客工具的不断发布&#xff0c;DDOS拒绝服务攻击的实施越来越容易&#xff0c;DDOS攻击事件正在成上升趋势。出于商业竞争、打击报复和网络敲诈等多种因素&#xff0c;导致很多商业站点、游戏服务器、聊天网络等网络服务商长期以来一…

Nacos 配置加密功能也太鸡肋了吧,有种更好的方式

大家好&#xff0c;我是风筝&#xff0c;微信搜「古时的风筝」&#xff0c;更多干货 当项目中用了 Nacos 做配置中心&#xff0c;是不是所有的配置都放到里面呢&#xff0c;大部分时候为了省事和统一&#xff0c;系统所有的配置都直接放在里面了&#xff0c;有时候&#xff0c…