内存操作函数(c语言)

目录

  • 概述
  • 1. `memcpy`函数
  • 2.`memcpy`函数的模拟实现
  • 3. `memcmp`函数
  • 4.`memcmp`函数的模拟实现
  • 5. `memset`函数
  • 6.`memset`函数的模拟实现
  • 7. `memmove`函数
  • 8.`memmove`函数的模拟实现
  • 结语

概述

C语言提供了一些非常有用的内存操作函数,其中包括memcpymemcmpmemsetmemmove。这些函数可以帮助我们在程序中对内存进行复制、比较和设置操作。本文将介绍这些函数的用法和模拟实现。

1. memcpy函数

memcpy函数用于将一个内存区域的内容复制到另一个内存区域。它的原型如下:

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

其中,destination是目标内存区域的指针,source是源内存区域的指针,number是要复制的字节数。下面是一个使用memcpy函数的示例:

#include <stdio.h>
#include <string.h>int main() 
{char src[] = "Hello, World!";char dest[20];memcpy(dest, src, 10);printf("复制后的字符串:%s", dest);return 0;
}
  • 输出结果:
    在这里插入图片描述
    上述代码将字符串src的前十个字节的内容复制到了dest数组中,但是并没有复制到'\0',所以在输出"Hello,Wor"之后是随机值。

2.memcpy函数的模拟实现

#include <stdio.h>
#include <assert.h>void* my_memcpy(void* dst, void* src, size_t num)//(拷贝目标地址,拷贝来源地址,要拷贝的字节大小)
{assert(dst && src);//assert()里面的条件必须为真,否则报错终止程序,这里是防止传过来的指针为NULLvoid* ret = dst;//memcpy函数拷贝完成后会返回目标的地址,这里先用ret将dst储存起来while (num--){*(char*)dst = *(char*)src;//强制类型转换为char*,是为了让程序一个字节一个字节的拷贝dst = (char*)dst + 1;src = (char*)src + 1;}return ret;
}int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = {0};my_memcpy(arr2, arr1, 20);for (int i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}
  • 输出结果
    在这里插入图片描述

3. memcmp函数

memcmp函数用于比较两个内存区域的内容是否相等。它的原型如下:

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

其中,ptr1ptr2分别是待比较的两个内存区域的指针,num是要比较的字节数。下面是一个使用memcmp函数的示例:

#include <stdio.h>
#include <string.h>int main() 
{char str1[] = "Hello";char str2[] = "Hello";int result = memcmp(str1, str2, strlen(str1));if (result == 0) {printf("两个字符串相等");} else {printf("两个字符串不相等");}return 0;
}
  • 输出结果
    在这里插入图片描述
    上述代码比较了两个字符串str1str2是否相等,并根据比较结果输出相应的信息。

4.memcmp函数的模拟实现

#include <stdio.h>
#include <assert.h>int my_memcmp(void* dst, void* src, size_t num)
{assert(dst && num);while (num--){if (*(char*)dst != *(char*)src)return *(char*)dst - *(char*)src;//memcmp函数的返回值是一个整型//当dst大于src时返回一个大于0的数//当dst等于src时返回0//当dst小于src时返回一个小于0的数//所以返回 dst - src 会方便很多	dst = (char*)dst + 1;src = (char*)src + 1;}return 0;
}int main()
{int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int arr2[] = { 1, 2, 3, 4, 6 };int ret = my_memcmp(arr1, arr2, 20);if (ret == 0)printf("相等");else if (ret > 0)printf("arr1大于arr2");elseprintf("arr1小于arr2");return 0;
}
  • 输出结果
    在这里插入图片描述
    上述代码比较的是arr1arr2的20个字节的内容,即比较了arr11,2,3,4,5arr21,2,3,4,6

5. memset函数

memset函数用于将一个内存区域的所有字节设置为指定的值。它的原型如下:

void *memset(void *dst, int src, size_t num);

其中,dst是要设置的内存区域的指针,src是要设置的值,num是要设置的字节数。下面是一个使用memset函数的示例:

#include <stdio.h>
#include <string.h>int main() 
{char str[20];memset(str, 'A', sizeof(str));printf("设置后的字符串:%s", str);return 0;
}
  • 输出结果
    在这里插入图片描述
    上述代码将字符串str中的所有字节都设置为字符'A',但是没有设置'\0',所以输出完20'A'之后是随机值。

6.memset函数的模拟实现

#include <stdio.h>
#include <assert.h>void* my_memset(void* dst, int src, size_t num)
{assert(dst);void* ret = dst;while (num--){*(char*)dst = (char)src;dst = (char*)dst + 1;}return ret;
}int main()
{char arr[10];my_memset(arr, '*', 10);for (int i = 0; i < 10; i++)printf("%c ", arr[i]);return 0;
}
  • 输出结果
    在这里插入图片描述

7. memmove函数

memmove函数用于将一个内存区域的内容移动到另一个内存区域即使这两个区域有重叠。它的原型如下:

void *memmove(void *dst, const void *src, size_t n);

其中,dst是目标内存区域的指针,src是源内存区域的指针,num是要移动的字节数。下面是一个使用memmove函数的示例:

#include <stdio.h>
#include <string.h>int main() 
{char str[] = "Hello, World!";memmove(str + 7, str, strlen(str) + 1);printf("移动后的字符串:%s", str);return 0;
}
  • 输出结果
    在这里插入图片描述
    上述代码将字符串str中的内容"Hello, World!"移动到了字符串str的第7个元素之后,结果如上图。

8.memmove函数的模拟实现

  • 模拟memmove函数的注意事项:
    1、当在内存中的地址dst < src时,memmove函数要将数据从前往后移动数据,否则会达不到想要的结果。
    2、当在内存中的地址dst = src时,从前往后和从后往前移动数据都可行。
    3、当在内存中的地址dst > src时,memmove函数要将数据从后往前移动数据,否则会达不到想要的结果。

  • 假设我们要将int arr[] = { 1,2,3,4,5,6,7,8,9,10 };中的前5个元素移动到第3个元素开始的位置,即将数组里的1,2,3,4,5移动到3,4,5,6,7

  • 因为第3个元素的地址小于第1个元素的地址,所以我们模拟的memmove函数要从后往前移动前5个元素,才能得到我们想要的结果

    • 下图分别是从前往后移动和从后往前移动的结果

在这里插入图片描述


模拟实现代码:

#include <stdio.h>
#include <assert.h>void* my_memmove(void* dst, void* src, size_t num)
{assert(dst && src);void* ret = dst;if (dst < src){while (num--){*(char*)dst = *(char*)src;dst = (char*)dst + 1;src = (char*)src + 1;}}else{while (num--){*((char*)dst + num ) = *((char*)src + num );//这里的num是经过--的,指向的是dst和src的最后一个元素的最后一个字节,如果不经过--,则会从dst和src的最后一个字节的后一个字节开始移动,会造成结果错误}}return ret;
}int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr + 2, arr, 20);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}
  • 输出结果
    在这里插入图片描述

结语

在使用这些内存操作函数时,需要注意传入正确的参数,并防止发生内存溢出或访问越界的情况。此外,这些函数在处理大量数据时效率较高,可以大大提高程序的执行效率和内存使用效率。

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

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

相关文章

MQTT简介

https://mqtt.org/ MQTT&#xff08;Message Queuing Telemetry Transport&#xff09; 一种轻量级的&#xff0c;基于发布订阅模式的通信协议&#xff0c;用于在物联网和机器与机器&#xff08;M2M&#xff09;通信中传输消息。 它具有低带宽和低功耗的特点&#xff0c;适用于…

vue3 开发记录

1.引入nprogress插件&#xff0c;显示未声明文件 无法找到模块“nprogress”的声明文件。 解决方法&#xff1a; vite-env.d.ts // 解决引入模块的报错提示 declare module "nprogress";2.在 .evn 文件中创建了自定义环境变量 VITE_APP_BASE_URL 但在项目中使用时出…

【学习记录】Resnet

Resnet的残差块 BasicBlock模块&#xff1a; Resnet的作用 解决梯度消失。网络越深&#xff0c;会导致梯度消失。Resnet可以解决梯度消失的问题。 Resnet的原理 参考视频&#xff1a;https://www.bilibili.com/video/BV1cM4y117ob/?spm_id_from333.337.search-card.all.cl…

请查收:2024年腾讯云服务器优惠价格表_租用配置报价

一张表看懂腾讯云服务器租用优惠价格表&#xff0c;一目了然&#xff0c;腾讯云服务器分为轻量应用服务器和云服务器CVM&#xff0c;CPU内存配置从2核2G、2核4G、4核8G、8核16G、4核16G、8核32G、16核32G、16核64等配置可选&#xff0c;公网带宽1M、3M、5M、12M、18M、22M、28M…

FreeRTOS任务切换

目录 一、PendSV异常 二、任务切换场合 1、执行系统调用 2、滴答定时器(SysTick)中断 三、PendSV中断服务函数 1、分析xPortPendSVHandler中断服务函数 四、查找下一个要运行的任务的两种方法 1、获取下一个要运行的任务 2、查找下一个要运行的任务的两种方法 2.1、通…

Windows系统安装TortoiseSVN并结合内网穿透实现远程访问本地服务器——“cpolar内网穿透”

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

ThreeDWorld(TDW)学习(待更新)

目录 前言 1.TDW 2.transport challenge 总结 前言 因为挑战赛了解到tdw仿真平台。 想了解的请点击&#xff1a; GitHub - threedworld-mit/tdw: ThreeDWorld simulation environment GitHub - chuangg/tdw-transport-challenge-starter-code 1.TDW ThreeDWorld (TDW)是一…

数据卷dockerfile

目录 一、数据卷 1. 简介 2. 数据卷和数据卷容器 1. 数据卷&#xff1a; 2. 数据卷容器&#xff1a; 二、自定义镜像 1. 作用 2. 自定义centos 3. 自定义tomcat8 一、数据卷 1. 简介 数据卷是一个可供一个或多个容器使用的特殊目录&#xff0c;它将主机操作系统目录直…

mysql修改字段的长度锁表问题

mysql修改字段的长度锁表问题 背景 MySQL&#xff08;这里指5.6及其后续版本&#xff09;修改字段的长度锁表会锁表吗&#xff1f;答案是可能会但不一定会 具体原理 MySQL 5.6 及以后版本扩大字段长度 支持 online ddl in-place 模式&#xff0c;而这将不会锁表。varchar 表示…

string字符串进行分割

c标准库中&#xff0c;对string字符串并没有提供分割操作&#xff0c;需要自己手动实现此功能。 方式1&#xff1a; 采用 std::stringstream 输入字符串&#xff0c;通过getline()函数&#xff0c;来对字符串进行分割。 #include <sstream>void getSplit(std::string s…

Unity—MVC分层开发思想

每日一句&#xff1a;当你不努力的时候&#xff0c;天赋就会一点一点被收回 目录 MVC分层开发思想 MVC是什么 MVC的开发步骤 案例&#xff1a;点击按钮实现金币进行添加&#xff0c;并且把金币记录到JSON里 MVC模式实现 背包系统基础代码 背包项目实现步骤 MVC分层开发思…

【vue+element ui】大屏自适应中el-select下拉内容在低分辨率下显示不全问题解决

目录 背景 现象 解决方案 背景 最近要把一个1920px*1080px的大屏改成自适应的&#xff1b;最低适配到1028px*720px&#xff1b; 现象 自适应适配改完之后 将电脑屏幕改成1028px*720px分辨率后&#xff0c;下拉显示正常 通过谷歌浏览器设置Toggle device toolbar为1028px*…

Fastjson2 <== 2.0.26反序列漏洞

根据Y4TACKER师傅在2023-03-20发布了一篇关于Fastjson原生反序列化的文章&#xff0c;文章中引入注目的是利用条件限制条件&#xff0c;不常常关注漏洞预警或者内容的几乎都是未发觉Fastjson2 到Fastjson2 2.0.26版本都有问题&#xff0c;其实如果单独去使用一些关键词去搜索&a…

Aws Ec2服务器设置密码登录

通过密钥&#xff0c;ssh登录到服务器 切换到root sudo -i开始设置root的新密码 passwd root输入并确认新密码即可 5.修改ssh配置文件 vim /etc/ssh/sshd_config6.重启sshd配置 systemctl restart sshd

QML中动态增加表格数据

1.QML中的表格实现 import QtQuick 2.15 import QtQuick.Window 2.15import QtQuick.Controls 2.0 import Qt.labs.qmlmodels 1.0 import QtQuick.Layouts 1.15Window {width: 640height: 480visible: truetitle: qsTr("Hello World")TableModel{id:table_modelTabl…

接口测试-幂等测试

我们知道一个网站的访问中会有很多各种各样的接口请求 比如说拿一个购物网站来说&#xff0c;有注册&#xff0c;有登录&#xff0c;有浏览商品&#xff0c;有添加购物车&#xff0c;查询购物车商品这些接口&#xff0c;还有一类特殊的接口&#xff0c;比如&#xff1a;支付。…

【JavaEE进阶】 Spring AOP详解

文章目录 &#x1f38b;前言&#x1f38d;Spring AOP核心概念&#x1f6a9;切点(Pointcut)&#x1f6a9;连接点(Join Point)&#x1f6a9;通知(Advice)&#x1f6a9;切面(Aspect) &#x1f340;通知类型&#x1f6a9;注意事项 &#x1f332;PointCut&#x1f384;切面优先级Ord…

深入理解Linux线程(LWP):概念、结构与实现机制(1)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;会いたい—Naomile 1:12━━━━━━️&#x1f49f;──────── 4:59 &#x1f504; ◀️ ⏸ ▶️ ☰ &a…

vue 解决:点击左侧相同菜单,右侧页面不重新加载的问题

1、问题描述&#xff1a; 其一、需求为&#xff1a; 无论是通过路由组件形成的平台管理系统&#xff0c;还是通过文件配置形成的平台管理系统&#xff0c;都存在通过切换左侧的导航栏而使右侧的页面切换的业务需求&#xff1b; 其二、问题描述为&#xff1a; A、步骤一&#…

基于RISC-V架构的通信DSP的设计以及在5G RedCap基带中的应用(五)-基于RISC-V的RedCap DSP在5G基带中的应用

4 基于RISC-V的RedCap DSP在5G基带中的应用 4.1 基带处理器的关键任务和性能需求 基带处理器是移动通信设备中的关键部件&#xff0c;负责处理无线信号&#xff0c;包括信号的接收、发送和处理。在5G通信系统中&#xff0c;基带处理器的关键任务和性能需求包括以下几个方面&a…