【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语言进阶】内存函数
天生我材必有用,千金散尽还复来。 ——李白 目录 前言 一.memcpy函数 1.实现memcpy函数 2.模拟实现memcpy函数 二.memmove函数 1.实现memmove函数 2.模拟实现memmove函数 三.memcpy函数和memmove函数的关系 四.memcm…...

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

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 标题:UPRISE:改进零样本评估…...
JS运行环境、包管理、打包工具总结
🌳JS运行环境-node.js 运行环境就是代码解析和执行的程序,比如jvm等虚拟机,他们的主要工作就是根据设定的语法规则解析编译代码,然后运行代码。 js的语法规则遵循ES规范。 🍁node.js Node.Js官网 Node.js是一种基于Ch…...

day4网络编程(广播和组播)
1.广播 发送端(类似于客户端) 流程: 创建套接字 填充接收端(服务器)网络信息结构体 bind(非必须绑定) 设置允许广播 向接收端(服务器)发送数据 关闭套接字文件 #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.数据信息可视化四、相关附件前言 在现代信息化时代,图形化用户界面(Graphical User Interface, GUI)已经成为各种软件应用和…...

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

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在当前文件进行文本查找 (必备)Ctrl R在当前文件进行文本替换 (必备)Ctrl Z撤销 (必备)Ctrl Y删除光标所在行 或 删除选中的行 (必备)Ctrl X剪切光标所在行…...
宝塔控制面板常用Linux命令大全
宝塔面板是站长朋友们常见的一款服务器运维面板,可以通过 Web 端轻松管理服务器,提升运维效率。大家在服务器中安装宝塔面板会用到宝塔面板特定的脚本命令。今天这篇文章为大家整理汇总了宝塔面板常用Linux命令,这样方便大家收藏查找。 1、安…...

C语言实现单链表(超多配图,这下不得不学会单链表了)
目录 一:什么是链表? 二:创建源文件和头文件 (1)头文件 (2)源文件 三:实参和形参 四:一步步实现单向链表 (1)建立一个头指针并置空 (2)打印链表,便于…...

SQL编写优化技巧
一、底层原理 sql慢是因为没有走索引,因此需要添加索引然它走索引联合索引需要匹配最左匹配原则(索引回表)如果查询列超出索引的key, 会导致回表,回表数量多,则会走全表扫描 索引是分聚集索引、非聚集索引…...

【基础算法】单链表的OJ练习(6) # 复制带随机指针的链表 #
文章目录🍇前言🍎复制带随机指针的链表🍑写在最后🍇前言 本章的链表OJ练习,是最后的也是最难的。对于本题,我们不仅要学会解题的思路,还要能够通过这个思路正确的写出代码,也就是思路…...
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语言期末真题实战
很简单的一道程序阅读题,pa’默认为a【0】,接下来会进行3次循环 0 1 2 输出结果即可 前3题就是一些基础定义,在此不多赘述 要注意不同的数据类型的字节数不同 a<<2 b>>1(b>>1;就是说b自身右位移一位(…...
【Shell】Shell变量
Shell变量系统预定义变量自定义变量基本语法定义变量撤销变量命名规则使用变量只读变量删除变量变量类型系统预定义变量 $HOME、$PWD、$SHELL、$SUSER等 实例 yysubuntu:~$ echo $HOME #查看系统变量的值 /home/yys yysubuntu:~$ set #显示当前shell中所有变量自定义变量…...

你是真的“C”——结构体中鲜有人知的“秘密”
你是真的“C”——结构体中的精髓剖析【内存对齐】 【位段】 😎前言🙌结构体内存对齐:😊结构体内存对齐存在的意思是什么?😘内存对齐例子详细剖析:😘结构体中的位段:&…...
2023年“网络安全”赛项江苏省淮安市赛题解析(超详细)
2023年中职组江苏省淮安市“网络空间安全”赛项 ①.2023年中职组江苏省淮安市任务书②.2023年中职组江苏省淮安市解析③.需要环境或者不懂的可以私信博主!①.2023年中职组江苏省淮安市任务书 任务一:服务器内部信息获取 任务环境说明: 服务器场景:Server210510(关闭链接…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...