内存操作函数

前言
🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨
🐻推荐专栏: 🍔🍟🌯 c语言进阶
🔑个人信条: 🌵知行合一
🍉本篇简介:>:介绍c语言中有关指针更深层的知识.
金句分享:
✨未来如星辰大海般璀璨✨
✨不必踌躇于过去的半亩方塘.✨
目录
- 前言
- 一、memcpy函数
- 函数模型:
- 函数参数:
- 函数的应用:
- 函数的模拟实现:
- 二、memmove函数
- 函数模型:
- 函数参数:
- 函数模拟实现
- 三、memcmp函数
- 函数模型:
- 函数参数:
- 函数应用:
- 模拟实现
- 四、memset函数
- 函数模型:
- 函数参数
一、memcpy函数
函数模型:

函数参数:
| 参数 | 意义 |
|---|---|
| destination | 指向目的地地址的指针,类型转换为 void* 类型的指针。 |
| source | 指向要复制的数据源的指针,类型转换为 const void* 类型的指针。 |
| num | 要复制的字节数 |
函数头文件:
#include <string.h>
函数功能:
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
注意:
要保证目的地址存的下源地址的内容,要守规矩哦!
1.为什么有了strcpy函数还要有memcpy函数呢?
因为strcpy函数是字符串拷贝,包括strncpy函数也是一样,只能拷贝字符串,对于其它类型,比如整形的拷贝就无能为力.
2.为什么要设置为void*类型?
如果看过前面qsort函数的模拟,这里应该也不难理解,因为要拷贝的类型是未知的,为了能够接收所有类型,所以设置为void*,使用时强制转换为char*类型,然后按字节个数拷贝即可.
函数的应用:
1.将arr2数组的前三个元素拷贝到arr1数组的前三个位置.
2.将字符串str2全部除了’\0’以外,拷贝到str1字符串.
#include <stdio.h>
#include <string.h>
int main()
{int arr1[10] = { 6,6,6,6,6,6,6,6,6,6 };int arr2[] = { 1,2,3,4,5,6,7,8 };int arr2sz= sizeof(arr2) / sizeof(arr2[0]);char str1[] = "XXXXXXXXXXXXXXXX";char str2[] = "Hello CSDN!";int str2sz= sizeof(str2) / sizeof(str2[0]);memcpy(arr1, arr2, sizeof(int) * 3);for (int i = 0; i < 10; i++){printf("%d ", arr1[i]);}printf("\n");memcpy(str1, str2, sizeof(char) * str2sz - 1);//-1是因为这里使用的是sizeof()函数计算的长度,会包括\0printf("%s", str1);printf("\n");return 0;
}
运行结果:
1 2 3 6 6 6 6 6 6 6
Hello CSDN!XXXXX
函数的模拟实现:
#include<assert.h>
void* my_memcpy(void* destination, const void* source, size_t num)
{assert(destination);assert(source);while (num--){//void*类型不可直接使用,要强制转化*(char*)destination = *(char*)source;//*是为了找到该地址所对应的字符串((char*)destination)++;//指针分别往后走,所以不需要解引用((char*)source)++;}
}
思考:
memcpy函数可以拷贝内存重叠的地址吗?
即source和destination有重叠的时候.(可以试试).
二、memmove函数
函数模型:

函数参数:
| 参数 | 意义 |
|---|---|
| destination | 指向目的地地址的指针,类型转换为 void* 类型的指针。 |
| source | 指向要复制的数据源的指针,类型转换为 const void* 类型的指针。 |
| num | 要复制的字节数 |
函数作用:
该函数与memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠
的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理,其实在有的编译器中,对于memcpy函数也进行了优化,也是允许内存重叠的.
但牛牛认为,还是有必要掌握这种更"稳妥"的函数的.
情况1

这种情况我们可以正常的从前向后(前->后) 拷贝.
即:先将6拷贝至2位置,再讲7拷贝至3位置……

这种情况我们使用从从前向后(前->后)拷贝则达不到我们的要求.
如果我们先将6拷贝至8处,7拷贝至9处,则原来的8 9都被修改了.
这时我们需要从后往前(后->前)拷贝.
即先将11拷贝至13处,再将9拷贝至12处……

其实这种情况并不是内存地址重叠,目的地址出现在前面也是一样的,都是可以从前向后(前->后)拷贝和从后往前(后->前)拷贝皆可.
函数模拟实现
#include <stdio.h>
#include<assert.h>
void* my_memmove(void* destination, const void* source, size_t num)
{void* ret = destination;//保留目的地原来的首地址assert(destination && source);//防止传错地址if (destination < source)//情况1时,目的地址的首地址小于源地址首地址{//前-->后while (num--){*(char*)destination = *(char*)source;((char*)destination)++;((char*)source)++;}}else{//后->前while (num--){*((char*)destination + num) = *((char*)source + num);//注意,这里如果以destination为1的偏移量,+num则是目的地地址的最后一个元素的地址.}}return ret;
}
代码测试:
情况1;
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,11,12,13 };//情况1my_memmove(arr + 1, arr + 5, sizeof(int) * 5);int sz= sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}
运行结果:
1 6 7 8 9 11 7 8 9 11 12 13
情况2:
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,11,12,13 };//情况1my_memmove(arr +7, arr + 5, sizeof(int) * 5);int sz = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}
运行结果:
1 2 3 4 5 6 7 6 7 8 9 11
三、memcmp函数
函数模型:

函数参数:
| 参数 | 意义 |
|---|---|
| ptr1 | 指向要比较的内容1,指针 |
| ptr2 | 指向要比较的内容2,指针 |
| num | 要比较的字节个数 |
函数头文件:
#include <string.h>
函数功能
比较从ptr1和ptr2指针开始的num个字节.
注意与strcmp函数区分:
strcmp函数:用于比较字符串是否相等,只用于比较字符
memcmp:按字节比较,两个指针所指向的内容是否相等.可用于比较不同类型的元素,但是是按字节比较.
| 返回值 | 意义 |
|---|---|
| <0 | 第一个不想等的字节中的值的str1的值小于str2中的值(arr1<arr2) |
| 0 | 两个指针的内容相等 |
| >0 | 第一个不相等的字节的str1的值大于于str2中的值(arr1>arr2 |
函数应用:
试着猜一下这段代码的值?(vs2022环境(小端))
//memcmp函数模拟
#include <stdio.h>
#include <string.h>
int main()
{int arr1[] = { 1,4,7,255 };int arr2[] = { 1,4,7,511 };int ret=memcmp(arr1, arr2, 13);printf("%d", ret);return 0;
}

答案:
0
解析:
首先这里是小端存储模式.则这两个数组在内存中存储的是:
arr1 :01 00 00 00 04 00 00 00 07 00 00 00 FF 00 00 00 (16进制,两位代表一个字节)
arr2 :01 00 00 00 04 00 00 00 07 00 00 00 FF 10 00 00
很明显,这里前四个元素(1,4,7)是相等的,而元素255和元素511则是第一个字节的内容相等,所以当比较的元素是[0,13]时,memcmp函数会认为这两个指针所指向的内容是相同的,故返回值是0.
可以试着改成14字节,返回值会是-1,因为第14个字节,arr1是00.arr2是1,则arr1<arr2;
模拟实现
#include<assert.h>
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{assert(ptr1 && ptr2);while (num--)//比较num个字节{if (*(char*)ptr1 == *(char*)ptr2)//相等继续往后比较{((char*)ptr1)++;((char*)ptr2)++;}else if (*(char*)ptr1 > *(char*)ptr2)//str1大则返回大于0的数{return 1;}else//str2大返回小于0的数{return -1;}}return 0;//比完了num个字节都相等则返回0
}
四、memset函数
函数模型:

头文件:
#include <string.h>
函数参数
| 参数 | 意义 |
|---|---|
| ptr | 指向要设置内容的空间 |
| value | 要设置的值,虽然是整形类型,但是也可以是字符,字符会转化为对应的ASCII码值 |
| num | 要设置空间内容的字节个数 |
函数功能:
将ptr所指向的空间,的num个字节设置为value值,注意这里也是按字节设置.
示例:
#include <stdio.h>
#include <string.h>
int main()
{int arr[5] = { 0 };memset(arr, 1, 20);for (int i = 0; i < 5; i++){printf("%d ", arr[i]);}return 0;
}
结果会是下面这个吗?
1 1 1 1 1
正确答案:
16843009 16843009 16843009 16843009 16843009
为什么呢?
我们可以试着通过调试找到答案.

执行语句memset(arr, 1, 40);后
很显然,这里是将20个字节设置为了1,而一个整形占4个字节;

那么怎样才可以将每个元素都设置为1呢?
#include <stdio.h>
#include <string.h>
int main()
{int arr[5] = { 0 };for (int i = 0; i < 5; i++){memset(arr+i, 1, 1);}for (int i = 0; i < 5; i++){printf("%d ", arr[i]);}return 0;
}
其实这样才能达到我们想要的结果,这里是将一个字节设置为1,然后跳过四个字节(下一个元素),再将这个元素的首字节设置为1.
但是这样是不是有点太麻烦了,所以一般memset函数一般不会这么用,一般memset函数用来将一段空间的元素按字节都初始化为0,在后面我们用到malloc函数向内存申请空间时,得到的空间里面存放的值都是随机值,这时我们可以使用它来帮助我们完成初始化操作.
好了,今天的内存操作函数就讲到这里了,我们下周再见!
最后,如果文章对大家有帮助的话,求一波三连吧!
💗💗💗886

相关文章:
内存操作函数
前言 🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:介绍c语言中有关指针更深层的知识. 金句分享: ✨未来…...
免费搭建个人博客
免费搭建个人博客,并发布到公网 利用hexo搭建个人博客,通过gitee的pages发布到公网 1 前置准备 安装git、安装node.js(尽量选择长期支持的版本) node.js官网:https://nodejs.org/en/ git官网:https://git-scm.com/book/zh/v2 安装…...
【Vue全家桶】详解Vue Router(一)
【Vue全家桶】Vue Router详解(一) Vue系列文章目录: 内容参考链接Vue(一)【Vue全家桶】邂逅Vue、Vue的多种引入方式Vue(二)【Vue全家桶】声明式编程、MVVMVue(三)【Vue…...
9大 HIVE SQL 最频繁被问到的面试题
SQL是用于数据分析和数据处理的最重要的编程语言之一,因此与数据科学相关的工作(例如数据分析师、数据科学家和数据工程师)在面试时总会问到关于 SQL 的问题。 SQL面试问题旨在评估应聘者的技术和解决问题的能力。因此对于应聘者来说&#x…...
学大数据算跟风吗?
随着互联网、物联网和人工智能等技术的不断发展,大数据技术逐渐进入人们的视野,成为一个备受关注的热点话题。那么,大数据专业好学吗?前景如何?下面我们来一起探讨一下。 一、大数据专业的学习难度 大数据技术是一种综…...
[C#]关于ListBox的坑
在用C#写个Demo程序的时候,使用ListBox保存读取到的每行内容。然后在重复读取的时候需要清除ListBox中的内容,我看到ListBox有清除的函数:lsbFiles.Items.Clear();以为这个函数就可以解决所有的问题,但是....于是想了个方法准备一…...
Apache POI 入门·第一话
文章目录1 摘要2 Apache POI2.1 介绍2.2 应用场景2.3 入门案例2.3.1 将数据写入Excel文件2.3.1.1 导入POI maven坐标2.3.1.2 代码开发2.3.1.3 实现效果2.3.2 读取Excel文件中的数据2.3.3 实现效果2.4 开发案例——导出运营数据Excel报表2.4.1 产品原型2.4.2 接口设计2.4.3 代码…...
8个python自动化脚本提高打工人幸福感~比心~
人生苦短,我用Python 最近有许多打工人都找我说打工好难 每天都是执行许多重复的任务, 例如阅读新闻、发邮件、查看天气、打开书签、清理文件夹等等, 使用自动化脚本,就无需手动一次又一次地完成这些任务, 非常方便…...
【嵌入式烧录/刷写文件】-1-详解Motorola S-record(S19/SREC/mot/SX)格式文件
目录 1 什么是Motorola S-record 2 Motorola S-record的格式 2.1 Motorola S-record的结构 2.1.1 “Record type记录类型”的说明 2.1.2 “Record length记录长度”的说明 2.1.3 如何计算“Checksum校验和” 2.2 Record order记录顺序 2.3 Text line terminator文本行终…...
图形视图界面 图形效果
Qt的标准图形效果类: QGraphicsBlurEffect提供模糊效果QGraphicsColorizeEffect提供染色效果QGraphicsDropShadowEffect提供阴影效果QGraphicsOpacityEffect提供透明效果 QGraphicsBlurEffect(模糊效果) 模糊效果会模糊源。此效果对于减少细…...
ElementUI学习笔记
目录 一、简单介绍 二、安装 1、下载 2、引入 三、布局 1、简介 2、使用 3、好处 四、布局容器 1、常见排布 2、调整样式 五、按钮 1、简单引用 2、改变样式 3、加载中效果 六、表格 1、简单使用 2、样式修改 七、对话框 1、简单使用 2、添加自定义内容 3、…...
安装KVM并创建虚拟机及基本使用
#环境说明:Centos7 环境准备: CPU开启虚拟化,给宿主机的CPU和内存分配足够多的配置 安装KVM 1.安装相关软件包 yum -y install qemu-kvm libvirt virt-manager virt-install virt-viewer 软件包简介: qemu-kvm: 为kvm提供…...
一种LCD屏闪问题的调试
背景 项目使用ESP32-S3 RGB接口驱动的LCD, 框架 idf-v5.0, LVGL-v7.11 显示画面正常, 但肉眼可见的像是背光在闪烁, 背光电路是应用很久的经典电路, 且排查背光驱动无错, 但开机一段时间后, 闪烁会明显减轻 记录 这块屏的显示驱动芯片为ST7701S, 查看芯片手册有说明特定的上…...
Java程序运行在Docker等容器环境有哪些新问题?
第30讲 | Java程序运行在Docker等容器环境有哪些新问题? 如今,Docker 等容器早已不是新生事物,正在逐步成为日常开发、部署环境的一部分。Java 能否无缝地运行在容器环境,是否符合微服务、Serverless 等新的软件架构和场景&#x…...
C语言面试最常问的三个关键字
文章目录前言一,static关键字的作用二,const 关键字的作用2.1, 修饰局部变量2.2,修饰指针2.3, 修饰函数形参2.4,修饰函数的返回值三,volatile关键字的作用前言 面试的时候,C语言最常…...
【Linux】-初识Linux
作者:学Java的冬瓜 博客主页:☀冬瓜的主页🌙 专栏:【Linux】 分享:逆着光行走,任风吹雨打。 ——《起风了》 主要内容:Linux的一些最基本指令,Linux的小程序,Linux关于连…...
精选7个 Python 学习资源库,助你成为优秀的开发者
当你在学习编程时,很容易被大量的资源所吓到,不知道该从何开始。 GitHub 仓库是一个很好的起点,因为它们提供了一种非常实用的方式来了解实际的编程应用。你可以查看其他人的代码,并将其与自己的代码进行比较和学习。 当涉及到 …...
【大数据处理与可视化】三 、Pandas库的运用
【大数据处理与可视化】三 、Pandas库的运用实验目的实验内容实验步骤一、使用pandas库分别创建Series对象和DataFrame对象,并对创建的对象使用索引、排序等相关操作;练习DataFrame对象的统计计算和统计描述的功能。1&2、创建一个DataFrame(d…...
FPGA解码SDI视频任意尺寸缩放拼接输出 提供工程源码和技术支持
目录1、前言2、SDI理论练习3、设计思路和架构SDI摄像头Gv8601a单端转差GTX解串SDI解码VGA时序恢复YUV转RGB图像缩放FDMA图像缓存实现拼接HDMI驱动4、vivado工程详解5、上板调试验证并演示6、福利:工程代码的获取1、前言 FPGA实现SDI视频编解码目前有两种方案&#…...
线索二叉树结构
线索二叉树结构1.线索二插树的作用2.线索二叉树的定义3.线索二叉树的结构4. 线索二叉树的操作4.1. 建立一棵中序线索二叉树4.2. 在中序线索二叉树上查找任意结点的中序前驱结点4.3. 在中序线索二叉树上查找任意结点的中序后继结点4.4. 在中序线索二叉树上查找任意结点在先序下的…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
