内存函数详解
1. memcpy函数
void * memcpy ( void * destination, const void * source, size_t num );
1.1 函数的功能,使用与注意事项
1. memcpy函数的作用是内存拷贝,即将source指向的空间中的num个字节拷贝到destination指向的空间中去,然后返回destination原本的值。
#include <stdio.h>
#include <string.h>
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };memcpy(arr2, arr1, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}
2. 该函数与strncpy不同之处在于,该函数在遇到'\0'时并不会停下来。
3. source与destination所指向的空间有任何重叠时,拷贝的结果都是未定义的。当需要进行这样的拷贝时,一般由下文会讲到的memmove函数完成。
对于第三点,给出以下示例
#include <stdio.h>
#include <string.h>int main()
{int arr[] = {1, 2, 3, 4, 5, 6, 7};memcpy(arr + 2, arr, 12);for(int i = 0; i < 7; i++){printf("%d ", arr[i]);}
}
此时,arr+2指向的空间与arr指向的空间是有重叠部分的,结果并不是我们所预期的“1 2 1 2 3 6 7”而是“1 2 1 2 1 6 7”(不同平台可能有不同的结果,vs2022和vscode输出的都是前者,因为他们对该函数的实现较为完善,与memmove的实现相似。按照C语言标准的规定,该函数的输出结果应该为后者)。
这是因为,当第一个整形拷贝完之后,source指向空间的前三个整形已经变成了“1 2 1”,继续拷贝下去,“1”就会被拷贝到原本“5”的位置上。
1.2 函数的模拟实现
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;
}
2. memmove函数
void * memmove ( void * destination, const void * source, size_t num );
2.1 函数的功能,使用与注意事项
基本与memcpy一样,但按照C语言标准规定,该函数才具备拷贝有重叠的空间的能力
2.2 函数的模拟实现
我们可以发现,之前memcpy无法做到重叠空间的拷贝的原因是,source指向空间中还未拷贝但预备拷贝的内容遭到了修改。
由于指向的空间有重叠的部分,所以source中一定会有内容被修改。但,问题是如何让这样的变化不影响拷贝呢?
当然是,确保重叠部分的空间都是在被拷贝之后再被修改。
当destination指向位置在source指向位置之后时,重叠部分位于source的后端,那么我们就应该从后端开始向前拷贝;
当destination指向位置在source指向位置之前时,重叠部分位于source的前端,那么我们就应该从前端开始向后拷贝。
void* my_memmove(void* dest, const void* src, size_t num)
{assert(dest && src);void* ret = dest;//dest在前,从前向后拷//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;
}
3. memset函数
void * memset ( void * ptr, int value, size_t num );
3.1 函数的功能,使用与注意事项
memset函数的作用是设置内存,即将ptr指向空间中的num个字节的值设置为value,然后返回ptr原本的值。
#include <stdio.h>
#include <string.h>int main ()
{char str[] = "hello world";memset (str,'x',6);printf("%S\n", str);return 0;
}
3.2 函数的模拟实现
void* my_memset(void* ptr, int value, size_t num)
{assert(ptr);while(num--){*((char*)ptr + num) = value;}return ptr;
}
4. memcmp函数
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
4.1 函数的功能,使用与注意事项
依次比较ptr1与ptr2指向空间中num个字节的值的大小。
若ptr1较大,返回大于零的数;
若ptr2较大,返回小于零的数;
若相同,则返回零。
该函数似乎意义不大,用到的地方很少,毕竟比较字节的大小似乎没有什么意义。
#include <stdio.h>
#include <string.h>int main()
{char buffer1[] = "DWgaOtP12df0";char buffer2[] = "DWGAOTP12DF0";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);elseprintf("'%s' is the same as '%s'.\n", buffer1, buffer2);return 0;
}
4.2 函数的模拟实现
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{assert(ptr1 && ptr2);while(*(char*)ptr1 == *(char*)ptr2 && num--){ptr1++;ptr2++;}return *(char*)ptr1 - *(char*)ptr2;
}
相关文章:
内存函数详解
1. memcpy函数 void * memcpy ( void * destination, const void * source, size_t num ); 1.1 函数的功能,使用与注意事项 1. memcpy函数的作用是内存拷贝,即将source指向的空间中的num个字节拷贝到destination指向的空间中去,然后返回de…...
事务(transaction)
事务,什么是事务,事务就是由单独单元的一个或多个sql语句组成,在这个单元中,每个sql语句都是相互依赖的。而整个单独单元是作为一个不可分割的整体存在,类似于物理当中的原子(一种不可分割的最小单位&#…...
Linux之cd、pwd、mkdir 命令
cd命令,切换目录 1)当Linux终端(命令行)打开的时候,会默认以用户的HOME目录作为当前的工作目录。 2)我们可以通过cd命令,更改当前所在的工作目录。 3)cd命令来自英文:C…...
【python高级编程教程】笔记(python教程、python进阶)第三节:(1)多态与鸭子类型(Polymorphism and Duck Typing)
参考文章1:【比刷剧还爽】清华大佬耗时128小时讲完的Python高级教程!全套200集!学不会退出IT界! 参考文章2:清华教授大力打造的Python高级核心技术!整整100集,强烈建议学习(Python3…...
学习JAVA的第十五天(基础)
目录 数据结构 二叉树 二叉查找树 平衡二叉树 红黑树 Set系列集合 HashSet集合 LinkedHashSet集合 TreeSet集合 前言:学习JAVA的第十四天(基础)-CSDN博客 数据结构 二叉树 元素:结点&am…...
LVS四层负载均衡集群
简介 LVS(Linux Virtual Server)即Linux虚拟服务器,是由章文嵩博士主导的开源负载均衡项目,目前LVS已经被集成到Linux内核模块中。该项目在Linux内核中实现了基于IP的数据请求负载均衡调度方案,终端互联网用户从外部访…...
【pyinstaller打包记录】程序使用多进程,打包后,程序陷入死循环
简介 PyInstaller 是一个用于将 Python 程序打包成可执行文件(可执行程序)的工具。它能够将 Python 代码和其相关的依赖项(包括 Python 解释器、依赖的模块、库文件等)打包成一个独立的可执行文件,方便在不同环境中运行…...
MAC | linux | SSH 密钥验证
SSH密钥登陆过程 客户端通过ssh-keygen生成自己的公钥和私钥。手动将客户端的公钥放入远程服务器的指定位置。客户端向服务器发起 SSH 登录的请求。服务器收到用户 SSH 登录的请求,发送一些随机数据给用户,要求用户证明自己的身份。客户端收到服务器发来…...
【AI Agent系列】【MetaGPT多智能体学习】3. 开发一个简单的多智能体系统,兼看MetaGPT多智能体运行机制
本系列文章跟随《MetaGPT多智能体课程》(https://github.com/datawhalechina/hugging-multi-agent),深入理解并实践多智能体系统的开发。 本文为该课程的第四章(多智能体开发)的第一篇笔记。主要记录下多智能体的运行…...
机器学习-面经(part7、无监督学习)
机器学习面经系列的其他部分如下所示: 机器学习-面经(part1) 机器学习-面经(part2)-交叉验证、超参数优化、评价指标等内容 机器学习-面经(part3)-正则化、特征工程面试问题与解答合集机器学习-面经(part4)-决策树共5000字的面试问题与解答…...
teknoparrot命令行启动游戏
官方github cd 到teknoparrot解压目录 cd /d E:\mn\TeknoParrot2_cp1\GameProfiles启动游戏 TeknoParrotUi.exe --profile游戏配置文件游戏配置文件位置/UserProfiles,如果UserProfiles文件夹里没有那就在/GameProfiles,在配置文件里将游戏路径加入之间,或者打开模拟器设置 …...
停止Tomcat服务的方式
运行脚本文件停止 运行Tomcat的bin目录中提供的停止服务的脚本文件 关闭命令 # sh方式 sh shutdown.sh# ./方式 ./shutdown.sh操作步骤 运行结束进程停止 查看Tomcat进程,获得进程id kill进程命令 # 执行命令结束进程 kill -9 65358 操作步骤 注意 kill命令是…...
多线程相关面试题(2024大厂高频面试题系列)
1、聊一下并行和并发有什么区别? 并发是同一时间应对多件事情的能力,多个线程轮流使用一个或多个CPU 并行是同一时间动手做多件事情的能力,4核CPU同时执行4个线程 2、说一下线程和进程的区别? 进程是正在运行程序的实例ÿ…...
mysql 时间精度问题
timestamp到2038年,还有14年时间,一个系统如果能活到那一刻也是相当不错了。 这里先看一下个datetime的问题,下面的插入数据的时间戳是2024-03-06 21:20:50.839 INSERT INTO psi_io_balance ( id, as_id, bill_date, order_id, busi_type, direction, c…...
基于python的爬虫原理和管理系统实现(代码下载)
Python实现爬虫的原理如下: 发送请求:使用Python中的库,如Requests或urllib,向目标网站发送HTTP请求,获取网页的内容。 解析网页:使用Python中的库,如BeautifulSoup或lxml,对获取的…...
IOS 设置UIViewController为背景半透明浮层弹窗,查看富文本图片详情
使用场景:UIViewController1 打开 UIViewController2(背景半透明弹窗) 案例:打开富文本网页<img>图片的url查看图片详情 WKWebView WKNavigationDelegate代理方法设置js代码点击事件 ///注册添加图片标签点击js方法 - …...
网络层介绍
网络层是OSI模型中的第三层,也称为网络协议层。它主要负责在源主机和目标主机之间提供数据通信的路径选择和控制。网络层通过使用源和目标主机的网络地址来实现数据包的路由和转发。 以下是网络层的一些主要功能: 路由选择:网络层使用路由选…...
springboot/ssm酒店客房管理系统Java在线酒店预约预定平台web
springboot/ssm酒店客房管理系统Java在线酒店预约预定平台web 基于springboot(可改ssm)vue项目 开发语言:Java 框架:springboot/可改ssm vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:…...
分布式测试插件 pytest-xdist 使用详解
使用背景: 大型测试套件:当你的测试套件非常庞大,包含了大量的测试用例时,pytest-xdist可以通过并行执行来加速整体的测试过程。它利用多个进程或计算机的计算资源,可以显著减少测试执行的时间。高计算资源需求&#…...
【S32K3 MCAL配置】-1.1-GPIO配置及其应用-点亮LED灯(基于MCAL)
目录(共13页精讲,手把手教你S32K3从入门到精通) 实现的架构:基于MCAL层 前期准备工作: 1 创建一个FREERTOS工程...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
