C语言内存函数的使用、剖析及模拟实现

目录

一、内存拷贝函数——memcpy

1.函数声明:

注意:

2.函数使用用例:

3.memcpy函数的模拟实现:

二、内存拷贝函数2——memmove

1.函数声明:

2.memmove函数的模拟实现

三、内存比较函数——memcmp

1.函数声明:

2.函数使用实例:

四、内存设置函数——memset

1.函数声明:

2,函数使用实例:


一、内存拷贝函数——memcpy

1.函数声明:

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

解释:

①:作用:将source所指向的空间的内容的前num个字节的内容拷贝到destination指向的空间。

②:该函数有三个参数:

第一个参数是个void*的指针,指向目的地空间;

第二个参数是个void*的指针,用于指向源头空间;

第三个参数类型为size_t,代表待拷贝的字节数。

③:该函数的返回类型为void*,即目标空间destination的起始地址。

④:该函数包含在头文件<string.h>中。

注意:

1.想到“拷贝”两个字,很多贴子可能会想到“strcpy”,但一定要注意,“strcpy”函数只能用于字符串拷贝,而“memcpy”函数可能拷贝不同类型的数据(int*、char*、...等等),所以我们还可以看到,该函数的形参的两个指针都是void*型,就是为了接收不同类型的数据。

2.memcpy函数只能用于处理不重叠的内存的拷贝(如将数组下标为1,2,3,4,5的内容拷贝到该数组下标为3,4,5,6,7的位置,这种情况下标为3,4,5的内存空间就是重叠了),否则会产生错误。重叠内存的拷贝由另外一个函数——memmove来实现,介绍在下文。

2.函数使用用例:

#include<stdio.h>
#include<string.h>
int main()
{//**********用例1***************************int arr1[10] = { 1,2,3,4,5,6,7,8,9,0 };int arr2[10] = { 0 };memcpy(arr2, arr1, sizeof(arr1));printf("arr2:");for (int i = 0; i < 10; i++){printf("%d ", arr2[i]);}printf("\n");//**********用例2****************************float arr3[5] = { 1.0,2.0,3.0,4.0,5.0 };float arr4[5] = { 0 };printf("arr4 ");memcpy(arr4, arr3, sizeof(arr3));for (int i = 0; i < 5; i++){printf("%f ", arr4[i]);}return 0;
}

用例运行结果:

3.memcpy函数的模拟实现:

①:源代码

//函数模拟实现
#include<stdio.h>
#include<string.h>
#include<assert.h>void* my_memcpy(void* dest, void* sour, size_t size)
{void* ret = dest;assert(dest && sour);while (size--){*(char*)dest = *(char*)sour;dest = (char*)dest + 1;sour = (char*)sour + 1;}return ret;
}
int main()
{int arr1[5] = { 1,2,3,4,5 };int arr2[5] = { 0 };my_memcpy(arr2, arr1, sizeof(arr1));for (int i = 0; i < 5; i++){printf("%d ", arr2[i]);}return 0;
}

解释:

①:因为是模拟实现,所以返回类型和参数类型都要相同。

②:因为返回值为目标空间的起始地址,所以开始先创建一个void*的指针将目标空间的起始地址dest保存起来。

②:因为void*指针不能用于加减和解引用操作,所以必须强制转换为其他类型的指针,所以就要思考转化为什么类型?因为是以字节为单位,所以很显然转为化char*指针就可以一字节一字节的拷贝。所谓拷贝无非就是赋值操作。

③:我们知道是以字节为单位进行拷贝,所以循环次数即为待拷贝字节数size,所以用一个while循环即可,循环体里面就是拷贝部分,先将两个指针转化为char*的指针,这样解引用的访问权限就是一个字节,这样依次赋值下去,最后在返回目标空间的起始地址ret即可。

二、内存拷贝函数2——memmove

1.函数声明:

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

解释:

①:我们发现该函数的返回类型及参数类型和“memcpy”函数都是一样的,不难理解,因为两者都是内存的拷贝,只是“memmove”函数有一点更高级的功能,就是可以对重叠的内存进行拷贝。

2.memmove函数的模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* dest, void* sour, size_t sz)
{assert(dest && sour);void* ret = dest;if (dest < sour){//前->后while (sz--){*(char*)dest = *(char*)sour;dest = (char*)dest + 1;sour = (char*)sour + 1;}}else{//后->前while (sz--){*((char*)dest+sz) = *((char*)sour+sz);}}return ret;
}int main()
{int arr[10] = { 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]);}int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("\n");my_memmove(arr1, arr1 + 2, 20);for (int i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}

运行结果:

三、内存比较函数——memcmp

1.函数声明:

  

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

解释:

①:该函数的作用就是将ptr1所指向的内容和ptr2所指向的内容进行比较,同样以字节为单位,但要注意的是,是以字节为单位进行比较,第三个参数num就是待比较字节数。

②:注意别和字符串比较函数“strcmp”混淆,“strcmp”只能用于字符串的比较,而此函数可以进行不同类型的数据的比较。

②:比较规则:(可参考函数“strcmp”)

若前大于后,返回一个大于0的数字;

若前等于后,返回0;

若前小于后,返回一个小于0的数字。

2.函数使用实例:

int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 1,2,3,4,6 };printf("%d\n", memcmp(arr1, arr2, 20));return 0;
}

很明显,arr1前四个数和arr2相同,但第五个数比arr2的第五个数小,所以会的到一个小于0的数,vs编译器默认这个小于0的数为-1,大于0的数为1.

四、内存设置函数——memset

1.函数声明:

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

①:函数的作用就是将ptr所指向的空间的内容的前num个字节的内容设置成第二个参数的值value,一定要注意是以字节为单位,可参考使用实例。

②:返回值为ptr指向的空间的起始地址。

2,函数使用实例:

本次知识到此结束,希望对你有所帮助!

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

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

相关文章

卸载Visual Studio 2010学习版 —— 卸载VCExpress

目录 最初安装Visual Studio 2010学习版是因为计算机二级 C语言考试而装&#xff0c;现如今考完试后便可卸载掉了&#xff0c;安装简便而卸载却没有uninstall.exe文件。故本文提供卸载方式。 进入到程序目录&#xff0c;找到setup.exe文件&#xff0c;也可以在程序目录搜索set…

【lesson10】进程状态

文章目录 认识进程状态新建运行阻塞挂起 Linux具体的进程状态RSDtTXZ是什么为什么 认识进程状态 上面就是各种进程状态&#xff0c;上面都是理论进程状态理论进程状态放在哪个操作系统中都是正确的&#xff0c;但是具体的操作系统实现可能又会有所不同。 下面我们来理解进程状态…

springBoot对接多个mq并且实现延迟队列---未完待续

mq调用流程 创建消息转换器 package com.wd.config;import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.context.annotation.Bean; import o…

Vue的详细教程--Vue路由与nodejs

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Vue的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Vue路由是什么 二.使用Vue路由的步骤 1、…

小程序中如何划分会员级别以及不同级别不同积分累计、折扣、返佣、升级条件等

以下是一些关键步骤和注意事项&#xff0c;帮助商家在小程序中有效设置会员卡等级和相关规则。 1. 设定会员卡等级。在管理员后台->会员管理处&#xff0c;点击“等级...”。会出现级别设置界面。 可以创建会员卡等级&#xff0c;并为每个等级设定名称和对应的规则。一般会员…

MyBatis 日志模块

文章目录 前言LogLogFactory日志应用JDBC 日志BaseJdbcLoggerConnectionLogger应用实现 总结 前言 日志在我们开发过程中占据了一个非常重要的地位&#xff0c;是开发和运维管理之间的桥梁&#xff0c;在Java中的日志框架也非常多&#xff0c;Log4j、Log4j2、slf4j等&#xff…

创建表

MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 创建表 语法格式: create table 表名(列名1 数据类型,列名2 数据类型,... ,列名n, 数据类型 ); 练习:在czwbkl库中,创建一格test01表 跟大家说…

开发高性能知识付费平台:关键技术策略

引言 在构建知识付费平台时&#xff0c;高性能是确保用户满意度和平台成功的关键因素之一。本文将探讨一些关键的技术策略&#xff0c;帮助开发者打造高性能的知识付费平台。 1. 前端性能优化 使用CDN加速资源加载 使用内容分发网络&#xff08;CDN&#xff09;来托管和加…

Flask数据库之SQLAlchemy--介绍--链接数据库

目录 SQLAlchemy介绍 SQLAlchemy连接数据库 SQLAlchemy介绍 数据库是一个网站的基础&#xff01;&#xff01;&#xff01; 比如MySQL、MongoDB、SQLite、PostgreSQL等&#xff0c;这里我们以MySQL为例进行讲解。 SQLAlchemy是一个ORM框架 对象关系映射&#xff08;英语&…

第一个 Go 程序“hello,world“ 与 main 函数

第一个 Go 程序"hello&#xff0c;world" 与 main 函数 文章目录 第一个 Go 程序"hello&#xff0c;world" 与 main 函数一.创建“hello&#xff0c;world”示例程序二. “hello&#xff0c;world” 程序结构拆解三、main 函数四、Go 语言中程序是怎么编译…

Xpath使用

有如下网页&#xff1a; 需要选中“若出现" 操作如下&#xff1a; 打开Xpath Helper 选中"若出现",右击检查 复制对应的Xpath 在QUERY栏插入即可

[杂谈]-快速了解半波和全波整流

快速了解半波和全波整流 文章目录 快速了解半波和全波整流1、滤波2、半波整流器3、全波整流器4、常见问题 整流器是一种将交流信号转换为脉动直流信号以及将交流电转换为直流电的电子电路。 我们日常生活中几乎所有的电子项目都会用到它。 根据周期传导&#xff0c;本文我们介绍…

VisualBox QA

出现提示注册表错误&#xff0c;或者之前正常&#xff0c;重启VisualBox后&#xff0c;VM运行失败时&#xff0c;可通过正确卸载VisualBox&#xff0c;然后使用注册表清理软件(CCleaner)清理注册表后&#xff0c;重装VisualBox&#xff0c;即会正常。&#xff08;一般用这个能解…

自学网络安全的三个必经阶段(含路线图)

一、为什么选择网络安全&#xff1f; 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来3-5年&#xff0c;是安全行业的黄金发展期&#xff0c;提前踏入…

「UG/NX」BlockUI 选择小平面区域 Select Facet Region

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「UG/NX」BlockUI集合&#x1f4da;全部专栏「UG/NX」NX二次开发「UG/NX」BlockUI集合「VS」Visual Studio「QT」QT5程序设计「C/C」C/C程序设计「Win」Windows程序设计「DSA」数据结构与算法「File」数据文件格式 目录 控件说…

vue3+ts 实现移动端分页

current 开始页码 pageSize 结束页码 const sizeref<number>(10) //一页显示十条 const eachCurrentPageref<number>(1) //默认是第一页interface ITdata {current: number,pageSize: number,// xxxx 其他参数... } const selectApplyList ref<…

Verilog 不同编码风格对综合电路的影响

文章目录 示例 #1示例 #2示例 #3 Verilog是一种硬件描述语言&#xff08;HDL&#xff09;&#xff0c;用于设计数字电路和系统。统一、良好的代码编写风格&#xff0c;可以提高代码的可维护性和可读性。 同样的功能&#xff0c;不同的Verilog 编码风格也会对综合过程产生重大影…

1787_函数指针的使用

全部学习汇总&#xff1a;GitHub - GreyZhang/c_basic: little bits of c. 前阵子似乎写了不少错代码&#xff0c;因为对函数指针的理解还不够。今天晚上似乎总算是梳理出了一点眉目&#xff0c;在先前自己写过的代码工程中做一下测试。 先前实现过一个归并排序算法&#xff0c…

【Java毕设项目】基于SpringBoot+Vue校园便利平台的设计与实现

博主主页&#xff1a;一季春秋博主简介&#xff1a;专注Java技术领域和毕业设计项目实战、Java、微信小程序、安卓等技术开发&#xff0c;远程调试部署、代码讲解、文档指导、ppt制作等技术指导。主要内容&#xff1a;毕业设计(Java项目、小程序等)、简历模板、学习资料、面试题…

【LeetCode-中等题】513. 找树左下角的值

文章目录 题目方法一&#xff1a;前序递归方法二&#xff1a;层序遍历 题目 方法一&#xff1a;前序递归 在递归遍历到叶子结点时&#xff0c;对比此时的节点深度&#xff0c;若当前节点深度大于当前最大深度&#xff0c;就更新value值&#xff0c;最后记录下的value即为最下最…