目录

  • 一、memcpy
    • 1.1 代码演示
    • 1.2 memcpy的模拟实现
  • 二、memmove
    • 2.1 代码演示
    • 2.2 模拟实现(小米面试题)
  • 三、memset
    • 3.1 代码演示
    • 3.2 总结
  • 四、memcmp
    • 4.1 代码演示
    • 4.2 总结
  • 总结


一、memcpy

(memory copy 内存复制)
之前文章中写的strcpy,strncpy函数是用来拷贝字符串的,是有局限性的,那么如何拷贝一个整型数组,或者结构体数组呢?
字符函数与字符串函数(上)
字符函数与字符串函数(下)
这就要用到memcpy了

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

功能

  • memcpy是完成内存块拷贝的,不关注内存中存放的数据是啥
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置
  • 如果source和destination有任何的重叠,复制的结果都是未定义的
    (内存重叠的情况使用memmove就行)
  • memcpy的使用需要包含<string.h>

参数
destination:指针,指向目标空间,拷贝的数据存放在这里
source:指针,指向源空间,要拷贝的数据从这里来
num:要拷贝的数据占据的字节数

返回值
拷贝完成后,返回目标空间的起始地址

1.1 代码演示

在这里插入图片描述
这里再展示一个浮点数的拷贝
在这里插入图片描述
这里数据显示的原因是浮点数在内存中无法精确保存,数组中的浮点数都要转换为二进制存到内存中去,这里小数点后的2转换为二进制很难,很可能写到50位都无法精确凑齐0.2
在这里插入图片描述
当然这里不知道多少个字节也可以算一下:
在这里插入图片描述

1.2 memcpy的模拟实现

在这里插入图片描述

在这里插入图片描述

乍一看,是不是觉得已经漂亮的实现了,实则暗藏漏洞
在这里插入图片描述
假设这里source空间的数据是1,2,3,4,5,覆盖到3,4,5,6,7上
结果如图:
在这里插入图片描述
预想情况下的覆盖情况应该是1 2 1 2 3 4 5 8 9 10,这里却是1 2 1 2 1 2 1 8 9 10
在这里插入图片描述
这里当3,4被1,2覆盖了之后,3就变为1,4就变为2,此时* (char* )src走到3的时候,走完4个字节就是1覆盖5,再往后就是变为2的4覆盖6,变为1的5覆盖7。所以就会监视就会出现这样的数据结果。

这就是另一种场景(内存重叠的情况使用memmove就行),但是呢这里memcpy又能正常的完成该场景的要求,也就是超常发挥了,500块的实力干了100块的活,这就是内卷。
在这里插入图片描述


二、memmove

(memory move 内存移动)

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

功能

  • memmove函数也是完成内存块拷贝的
  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
  • memmove的使用需要包含<string.h>

参数返回值与memcpy是一样的

2.1 代码演示

在这里插入图片描述
在这里插入图片描述

2.2 模拟实现(小米面试题)

内存重叠拷贝根据memcpy写的内容有两种情况

第一种情况

在这里插入图片描述
这里src<dest(数组随着下标的增长,地址是由低向高变化的),就必须从src的末尾数据5开始,向着dest的末尾数据7从后向前拷贝,否则从前向后拷贝就会出现1 2 1 2 3 4 5 8 9 10的情况。

第二种情况

在这里插入图片描述
当dest<src的时候,就必须从src的其实数据3开始,向着dest的起始数据1开始从前向后拷贝。这样才不会出错。

memmove底层逻辑也是基于这些情况实现的
memmove的拷贝是分三种情景的

第一种情景

在这里插入图片描述
这里是dest<src的情景,需要从前向后拷贝

第二种情景

在这里插入图片描述
这里是src<dest,需要从后向前拷贝
前两种情景都是dest与src有内存重叠的情况下的考量。
在这里插入图片描述
第三种情况dest的内存与src的内存已经完全脱离了,无论哪种拷贝方式都是可以的。
在这里插入图片描述
这里给每种情景标号。

写代码的方案就可以分两种

  1. 1,3从前向后拷贝,2从后向前拷贝
  2. 1 从前向后拷贝,2,3从后向前拷贝

我个人还是觉得方案二更好一些,找 1 与 2 3 的边界就够,方案一则要找1与2的边界,2与3的边界,相对麻烦。

#include<assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;if (dest < src)//1{//从前向后拷贝while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else{//从后向前拷贝while (num--){//跳过19个字节,指向第20个字节*((char*)dest + num) = *((char*)src + num);}}return ret;
}int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//my_memmove(arr + 2, arr, 20);my_memmove(arr, arr + 2, 20);return 0;
}

这里再说一下这里类型转换的问题

dest = (char*)dest + 1;
src = (char*)src + 1;

在表达式 (char*)src + 1 中:
(char* )src:将 src(const void* 类型)临时转换为 const char* 类型。
结果类型:表达式 (char* )src + 1 的结果类型是 const char*,指向原地址后一个字节的位置。

在赋值语句 src = (char*)src + 1; 中:
左值 src:类型为 const void*(函数参数类型)。
右值 (char* )src + 1:类型为 const char* 。
C 语言允许将任意类型的指针隐式转换为 void* 或 const void* ,因此 const char* 可以直接赋值给 const void* ,无需显式强制类型转换。


三、memset

(memory move 内存设置)

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

功能

  • memset函数是用来设置内存块的内容的,将内存中指定长度的控件设置为特定的内容。
  • memset的使用需要包含<string,h>

参数
ptr:指针,指向要设置的内存空间,也就是存放了要设置的内存空间的起始地址。
value:要设置的值,函数将会把value值转换成unsigned char的数据进行设置的。也就是以字节为单位来设置内存块的。
num:要设置的内存长度,单位是字节。

返回值:返回的是要设置的内存空间的起始地址。

3.1 代码演示

在这里插入图片描述
这是一个字符数组元素的设置,那么整型数组元素能不能设置呢?
在这里插入图片描述

在这里插入图片描述
可以看到是不可以的,memset是以字节为单位设置的,它把每一个字节设置为01,也就是1,而1的16进制的表示是0x 00 00 00 01,所以是达不到所设想的要求的。

但是它可以把整型数组的每个元素设置为0
在这里插入图片描述
它把每个字节设置为0,每个元素也就会变为0了。

3.2 总结

当有一块内存空间需要设置内容的时候,就可以使用memset函数,值得注意的是memset函数对内存单元的设置是以字节为单位的。

四、memcmp

(memory compare)

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

功能
比较指定的两块内存块的内容,比较从ptr1和ptr2指针指向的位置开始,向后的num个字节。
memcmp的使用需要包含<string.h>

参数
ptr1:指针,指向一块待比较的内存块。
ptr2:指针,指向另一块待比较的内存块。
num:指定的比较长度,单位是字节。

返回值

返回一个整数值,指示内存块内容之间的关系:

返回值含义说明
< 0两个内存块中第一个不匹配字节,在 ptr1 中对应的值(按 unsigned char 值计算)小于在 ptr2 中的值
0两个内存块的内容相等
> 0两个内存块中第一个不匹配字节,在 ptr1 中对应的值(按 unsigned char 值计算)大于在 ptr2 中的值

4.1 代码演示

这里比较前16个字节相等
在这里插入图片描述
但如果比较前17个呢?
在这里插入图片描述
结果如预期所设想。

4.2 总结

如果要比较2块内存空间的数据的大小,可以使用memcmp函数,这个函数的特点就是可以指定比较长度。
memcmp函数是通过返回值告知大小关系的。


总结

以上就是C语言内存函数的全部内容了,下午也是上网冲浪的时候发现了小米的暑期实习面试题有我所写的内容,也是非常开心哈哈,毕竟证明了自己所学都是有价值的,而且是贴近就业的,喜欢作者文章的靓仔靓女们不要忘记一键三连支持一下~
你们的支持就是我最大的动力。

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

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

相关文章

DK124反激式开关电源芯片

18W 高性能交直流转换芯片 特性 DK124 是一款离线式开关电源芯片&#xff0c;最大输出功率达到 24W。内部集成了 PWM 控制器、700V 功率管和初级峰值电流检测电路&#xff0c;并采用了可以省略辅助供电绕组的专利自供电技术&#xff0c;极大简化了外围应用电路&#xff0c;减…

商品销售数据分析实验

进入虚拟机&#xff0c;启动HDFS和Yarn1.创建表 hive show databases; use test;销售订单表create table t_dml (detail_id bigint,sale_date date, province string,city string,product_id bigint,cnt bigint,amt double )row format delimited fields terminated by ,;商品…

PH热榜 | 2025-07-08

1. TensorBlock Forge 标语&#xff1a;人工智能模型的API 介绍&#xff1a;Forge是一个快速且安全的工具&#xff0c;让你可以跨不同供应商连接和运行AI模型 产品网站&#xff1a; 立即访问 Product Hunt&#xff1a; View on Product Hunt 票数&#xff1a; &#x1f53a…

2025-01)electronjs-v11.2.0升级到新版本electronjs-v37.2.0记录,node版本记录,淘宝镜像配置记录,升级记录

背景:由于22年使用electronjs开发的自助机客户端几年没去维护,现在有需求要修改,电脑也换新了,node环境也没,直接把electron从 之前的 11.2.0 版本 升级到了37.2.0版本,升级最主要的目的是升级谷歌浏览器内核,升级后谷歌浏览器内核直接从87升级到了138,可以支持谷歌最新…

iQOO手机怎样相互远程控制?其他手机可以远程控制iQOO吗?

iQOO是Vivo同一品牌下的产品&#xff0c;它们两款手机都可以使用手机内置的远程控制功能。具体做法是&#xff0c;打开控制端的iQOO手机的【设置】【快捷与辅助】、【远程协助】&#xff0c;然后输入被控端的电话号码&#xff0c;等被控端的手机接受远程协助后&#xff0c;就可…

【入门级-C++程序设计:3、程序基本语句-多层循环语句】

1、定义&#xff1a; 在 C 中&#xff0c;多层循环&#xff08;嵌套循环&#xff09;是指在一个循环体内包含另一个或多个循环语句。它常用于处理多维数据结构&#xff08;如二维数组&#xff09;、复杂的迭代逻辑&#xff08;如矩阵运算、图形打印、组合遍历等&#xff09;。多…

四、jenkins自动构建和设置邮箱

一、jenkins自动构建什么自动构建、有啥用&#xff1a;触发方式代码提交&#xff08;Git push&#xff09;定时任务&#xff08;如每天凌晨构建&#xff09;手动点击等方式&#xff08;立即执行&#xff09;执行内容从 Git/SVN 拉取最新代码运行编译&#xff08;如 Maven/Gradl…

【深度学习新浪潮】深入解析LLM关键概念:架构、优化与最新研究进展

1. Transformer架构与注意力机制 概念解析 Transformer是LLM的核心架构,由编码器和解码器组成,其核心创新是自注意力机制,通过计算输入序列中每个位置的关联权重,动态聚焦关键信息。自注意力机制的计算复杂度为O(n),在处理长序列时成为性能瓶颈。 代码示例:基础Transfo…

RAGflow图像解析与向量化分析

RAGflow图像解析与向量化分析 注:需要提前部署好ragflow,才方便一 一对应代码,部署教程:rag部署教程,这样才会方便后续更改 1. 图像解析流程 RAGflow通过多种解析器处理不同类型的文档,其中图像解析是一个重要组成部分。以下是RAGflow处理图像的主要流程: 1.1 PDF文…

千翼破界,百景赋能 | 2025深圳eVTOL展无人机场景应用专场即将启幕

在技术革新、应用深化、产业链协同升级及低空空域管理改革等多重政策红利驱动下&#xff0c;我国工业级无人机产业正迈入爆发式增长新阶段&#xff0c;持续引领民用无人机市场繁荣。数据显示&#xff0c;2019 至2024年&#xff0c;我国民用无人机市场规模从435.1亿元跃升至1108…

Go语言标识符命名规则详解:工程化实践

引言 Go语言的命名规则是其简洁哲学和工程实用性的集中体现。下面从语法规范、最佳实践到实际应用进行全面解析&#xff1a; 一、基础命名规则 1. 变量命名 // 小驼峰式&#xff08;lowerCamelCase&#xff09; var userName string var maxRetryCount 3 var isConnected bool…

RISC-V:开源芯浪潮下的技术突围与职业新赛道 (一)为什么RISC-V是颠覆性创新?

第一篇&#xff1a;开篇&#xff1a;为什么RISC-V是颠覆性创新&#xff1f; 打破70年架构垄断&#xff0c;开源硬件如何重塑芯片产业规则&#xff1f;一、传统架构的“围城之困”&#xff08;痛点切入&#xff09; ARM/X86的统治代价 授权费暴利模型 &#xff1a; ARM指令集授权…

【机器学习笔记 Ⅱ】7 多类分类

1. 多类分类&#xff08;Multi-class Classification&#xff09; 定义 多类分类是指目标变量&#xff08;标签&#xff09;有超过两个类别的分类任务。例如&#xff1a; 手写数字识别&#xff1a;10个类别&#xff08;0~9&#xff09;。图像分类&#xff1a;区分猫、狗、鸟等。…

2025年深圳杉川机器人性格测评和Verify测评SHL题库高分攻略

1、杉川机器人包含性格测评和Verify测评&#xff0c;预计用时60min&#xff0c;请确保作答时周围环境无干扰、网络畅通&#xff1b;2、请使用电脑完成作答&#xff0c;建议使用以下浏览器登录&#xff1a;IE9.0及以上版本&#xff0c;火狐&#xff0c;谷歌&#xff1b;3、杉川机…

【flutter 在最新版本中已经弃用了传统的 apply from 方式引入 Gradle 插件】

报错 Flutter assets will be downloaded from https://storage.flutter-io.cn. Make sure you trust this source! Launching lib\main.dart on 2112123AC in debug mode... Running Gradle task assembleDebug...FAILURE: Build failed with an exception.* Where: Script D…

Web后端实战:(部门管理)

1.准备工作 1.1开发规范 1.1.1前后端分离开发 我们目前基本都是采用的前后台分离开发方式&#xff0c;如下图所示&#xff1a; 那么基于前后台分离开发的模式下&#xff0c;我们后台开发者开发一个功能的具体流程如何呢&#xff1f;如下图所示&#xff1a; 需求分析&…

字节寻址(Byte Addressing) 与 Verilog中的寄存器索引

字节寻址&#xff08;Byte Addressing&#xff09; 与 Verilog中的寄存器索引 之间的关系。 您的疑问非常正确&#xff0c;直接看 3h1 很容易让人以为地址就是 0x01。 但答案是&#xff1a;是的&#xff0c;3h1 在这里对应的字节地址&#xff08;Byte Address&#xff09;确实是…

Ubuntu远程桌面

方法1: 检查并使用已安装的VNC或远程桌面组件 请在终端中执行以下命令检查系统中已安装的相关组件: bash# 检查系统中已安装的VNC和远程桌面相关软件 dpkg -l | grep -E "vnc|vino|remote|rdp"# 检查常见远程桌面服务 which vino-server tigervncserver x11vnc xr…

WEB攻防-文件包含LFIRFI伪协议编码算法无文件利用黑白盒

知识点&#xff1a; 1、文件包含-原理&分类&危害-LFI&RFI 2、文件包含-利用-黑白盒&无文件&伪协议 一、演示案例-文件包含-原理&分类&利用 1、原理 程序开发人员通常会把可重复使用的函数写到单个文件中&#xff0c;在使用某些函数时&#xff…

LabVIEW的GPIB仪器校准

基于LabVIEW开发平台与 GPIB 总线技术&#xff0c;采用是德科技、泰克等硬件设备&#xff0c;构建示波器与频谱分析仪自动校准系统。通过图形化编程实现校准流程自动化&#xff0c;涵盖设备连接、参数配置、数据采集、误差分析及报告生成&#xff0c;显著提升校准效率与精度&am…