【C进阶】第十五篇——内存函数

news2024/11/28 17:48:48

memcpy - 内存拷贝1

函数介绍

模拟实现

memmove - 内存拷贝2

函数介绍

模拟实现

memcmp - 内存比较

memset - 内存设置


memcpy - 内存拷贝1

函数介绍

void *memcpy( void *dest, const void *src, size_t count );

 memcpy函数是一个用于拷贝两个不相关的内存块的函数。memcpy函数会从src的位置开始向后复制count个字节的数据到dest的内存位置,并返回dest的首地址。

注意:

  • memcpy函数在遇到'\0’的时候并不会停下来。
  • 若dest和src有任意重叠,复制的结果都是未定义的(未拷贝内容被覆盖)
  • memcpy函数在实现的时候,不知道未来会被用来拷贝什么样的数据。所以参数的指针类型为void*(可接收任意类型指针)

比如我们要将数组中的1,2,3,4拷贝到arr2数组中。

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1, 16);
	for (int i = 0; i < 4; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

 运行结果:因为一个整型的大小是4个字节,而我们要拷贝4个整型到arr2中,所以传参的时候第三个参数count的大小为16.

模拟实现

进入函数体首先保存dest的起始位置,便于之后返回。然后循环count次,每次将src中的一个字节的内存数据拷贝到dest中的对应位置,然后dest和src指针后移继续拷贝,拷贝结束后返回dest原来的首地址即可。

void* my_memcpy(void* dest, const void* src, size_t count)
{
	assert(dest != NULL);//断言,当dest为空指针时报错
	assert(src != NULL);//断言,当src为空指针时报错
	void* ret = dest;//保存dest,便于之后返回
	while (count--)//循环count次,每次拷贝1个字节
	{
		*(char*)dest = *(char*)src;
		++(char*)dest;
		++(char*)src;
	}
	return ret;
}

 注意:在对dest和src指针进行操作时,要先将它们强制类型转换为char* 类型的指针。(char* 类型的指针可以向后访问一个字节的内容)

memmove - 内存拷贝2

函数介绍

void *memmove( void *dest, const void *src, size_t count );

我们发现memmove函数的参数和返回值与memcpy函数一模一样。没错,memmove函数和memcpy函数的功能一样,也是从src的位置开始向后复制count个字节的数据到dest的内存位置,并返回dest的首地址。
那么它们有什么不同呢?
memmove函数和memcpy函数的差别就是,memmove函数的源内存块和目标内存块是可以重叠的,而memcpy函数的源内存块和目标内存块是不可以重叠的。
举个例子,比如我们要将arr数组中的1,2,3,4拷贝到3,4,5,6的位置上去,让arr数组变为1,2,1,2,3,4,7,8,9,10。

#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	memcpy(arr + 2, arr, 16);
	return 0;
}

 但结果操作后arr数组中的数据变为1,2,1,2,1,2,7,8,9,10。

我们可以看到,此时源内存块和目标内存块就发生了重叠。我们先把1,2拷贝放到了3,4的位置,但当我们想把3,4拷贝放到5,6的位置的时候发现3,4位置上放的数字变成了1,2,所以就把1,2拷贝放到了5,6的位置,于是数组就变成了1,2,1,2,1,2,7,8,9,10。
memmove函数便可以很好的解决这个问题。所以当源内存块和目标内存块发生重叠的时候,就得使用memmove函数处理。

模拟实现

我们发现,当源内存块和目标内存块发生重叠的时候,我们不能像memcpy函数一样直接从前向后依次拷贝,我们需要分情况讨论。

通过画图,我们可以根据dest指针和src指针的相对位置将情况分为三类:
第一类:dest指针位于src内存块左边,采用从前向后拷贝。
第二类:dest指针位于src内存块内,采用从后向前拷贝。
第三类:dest指针位于src内存块右边,采用从前向后和从后向前均可以。
注:当dest指针与src指针位于同一位置时不用拷贝。

void* my_memmove(void* dest, const void* src, size_t count)
{
	assert(dest != NULL);//断言,当dest为空指针时报错
	assert(src != NULL);//断言,当src为空指针时报错
	void* ret = dest;
	if (dest < src)//从前往后拷贝
	{
		while (count--)
		{
			*(char*)dest = *(char*)src;
			++(char*)dest;
			++(char*)src;
		}
	}
	else if (dest>src)//从后往前拷贝
	{
		while (count--)
		{
			*((char*)dest + count) = *((char*)src + count);
		}
	}
	return ret;
}

memcmp - 内存比较

int memcmp( const void *buf1, const void *buf2, size_t count );

 memcmp函数是一个用于比较两个内存块大小的函数。它会比较从buf1和buf2指针开始的count个字节,当buf1大于buf2的时候返回一个大于0的数;当buf1等于buf2的时候返回0;当buf1小于buf2的时候返回一个小于0的数。
举个例子:

#include<stdio.h>
#include<string.h> 
int main()
{
	int arr1[] = { 1, 2, 3, 4 };
	int arr2[] = { 1, 2, 4, 5 };
	int ret1 = memcmp(arr1, arr2, 8);
	int ret2 = memcmp(arr1, arr2, 9);
	return 0;
}

 在VS编译器下,内存采用的是小端存储方式,arr1和arr2在内存中的存储形式如图所示:

 所以,当比较字节数为8时,返回值为0;当比较字节数为9时,返回值为一个负数。

memset - 内存设置

void *memset( void *dest, int c, size_t count );

memset函数可以将内存块的某一部分设置为特定的字符。三个参数中,第一个参数是开始设置内存的起始位置,第二个参数是要将内存设置成的字符,第三个参数是从起始位置开始需要设置的内存字节数。

注意:

  • memset函数设置内存的时候是一个字节一个字节地设置的。

举个例子,比如我们要将"hello world!"字符串的前5个字符设置成'*'.

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "hello world!";
	memset(arr, '*', 5);
	return 0;
}

 运行结果:

 

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

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

相关文章

4-2文件管理-文件系统实现

文章目录一.文件系统层次结构二.文件系统的全局结构三.虚拟文件系统与文件系统挂载&#xff08;安装&#xff09;&#xff08;一&#xff09;虚拟文件系统&#xff08;二&#xff09;文件系统挂载&#xff08;安装&#xff09;一.文件系统层次结构 &#xff08;1&#xff09;用…

密码学_MD5算法

MD5即Message-Digest Algorithm 5&#xff08;信息-摘要算法5&#xff09;&#xff0c;用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一&#xff08;又译摘要算法、哈希算法&#xff09;&#xff0c;主流编程语言普遍已有MD5实现。 MD5算法具有以下特点&#xff1a…

php宝塔搭建部署实战易优cms皮具皮包手袋定制网站源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套php开发的易优cms皮具皮包手袋定制网站源码&#xff0c;感兴趣的朋友可以自行下载学习。 技术架构 PHP7.2 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码&a…

Java 日常开发记录

手动分页 非mybatis 自动分页 service 层 Overridepublic PageInfo<CfLogVo> cfLogList(CfLogQuery cfLogQuery) {if (StrUtil.isNotBlank(cfLogQuery.getRequest()) && cfLogQuery.getRequest().length() >100){throw new ServiceException("请求报文…

Flutter | 使用 typedef 让回调更优雅

今天来谈谈 Flutter 的 typedef。 一. 熟悉的 VoidCallback 之前看 setState 源码的时候&#xff0c;发现它的参数是 VoidCallback&#xff1a; void setState(VoidCallback fn) {}VoidCallback 其实是一个自定义类型的无参数无返回值的匿名函数&#xff1a; /// Signature…

mybatis之配置优化and映射器

环境配置&#xff1a; mybatis可以配置成适应多种环境&#xff0c;但是要记住&#xff0c;尽管可以配置多个环境&#xff0c;但每个SqlSessionFactory实例只能选择一种环境。 虽然&#xff0c;MyBatis 中有两种类型的事务管理器:type("[JDBC|MANAGED]"&#xff09;…

Web进阶:Day3 移动端特点、百分比布局、Flex布局、实战演练

Web进阶&#xff1a;Day3 Date: January 7, 2023 Summary: 移动端特点、百分比布局、Flex布局、实战演练 移动端特点 移动端和PC端网页不同点 PC端网页和移动端网页的有什么不同&#xff1f; PC屏幕大&#xff0c;网页固定版心 手机屏幕小&#xff0c; 网页宽度多数为100%…

【Docker】(五)使用bind mounts修改Docker容器中的Nginx配置

1.前言 本系列文章记录了从0开始学习Docker的过程&#xff0c;Docker系列历史文章&#xff1a; &#xff08;一&#xff09;基本概念与安装使用 &#xff08;二&#xff09;如何使用Docker发布一个SpringBoot服务 &#xff08;三&#xff09;使用registry远程镜像仓库管理镜像…

axios拦截器、ElementUI

一、axios拦截器 1、axios模块的作用 是对基于http请求的封装。在浏览器对异步请求对象XMLHttpRequest进行封装 2、拦截器 ​ &#xff08;1&#xff09;请求拦截器&#xff1a;对客户端发起的请求进行统一的前期处理&#xff08;token、时间戳、cookie等&#xff09; ​ …

linux系统中利用QT实现绘制图和图标的方法

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何使用QT进行绘图和图标的方法。 第一&#xff1a;绘图和图表简介 绘图与图表在嵌入式里有的比较多&#xff0c;尤其是图表&#xff0c;我们常在股票里看到的“图表折线/曲线图/饼状图等”都可以用 Qt 的图表来实现。绘图…

生产制造业如何谋求数字化转型?需要哪些信息化系统做支撑?

生产制造业数字化转型有什么思路&#xff1f;生产制造业需要哪些信息化系统做支撑&#xff1f; 近年来&#xff0c;围绕新产品新模式新业态&#xff0c;国家重点部署了7个方向&#xff0c;包括数字化管理、平台化设计、智能化生产、网络化协同、个性化定制、服务化延伸、新型智…

Revit图纸问题:设置dwg图纸显示顺序和批量图纸编号

一、Revit中设置导入的dwg图纸的显示顺序 我们在实际工作中经常需要将各种DWG图纸导入到revit中进行参考&#xff0c;有时候希望它盖住已有模型&#xff0c;有时候又需要它在模型以下显示&#xff0c;即实现类似于CAD的图层显示顺序功能&#xff0c;应该如何才能实现呢&#xf…

Window Server 2022 无法安装网卡驱动 1219-v

安装过win10的朋友都知道,win10基本上不用自己下载驱动. 插上网线就能用. 但是今天在server2022上,死活无法安装成功. 原因有很多,网上也有很多资料. 重点: 其实不需要修改驱动配置, 只需要在驱动中选择对应驱动,比如: 1219[x]-LM,x标识很多版本,选择一个低一点的就可以了. …

MySQL - explain 执行计划详解

explain显示了MySQL如何使用索引来处理select语句以及连接表&#xff0c;可以帮助选择更好的索引和写出更优化的查询语句。 explain 查询结果如下&#xff1a; 字段说明&#xff1a; 列名说明id id列的编号是select的序列号&#xff0c;有几个select就有几个id&#xff0c;并…

IPEmotion的NVH噪声测试模块——坎贝尔图

德国IPETRONIK的IPEmotion软件除了可以对之前介绍的热管理试验及热管理台架试验、电性能试验和道路试验等各种进行基本的温度、模拟量和数字信号的采集分析外&#xff0c;无论专业版、开发版还是分析版均支持噪声分析模块。该模块支持噪声数据离线后处理&#xff0c;包括Campbe…

如何通过大数据赋能产业园区高质量发展

2022年年底&#xff0c;中共中央、国务院印发了《关于构建数据基础制度更好发挥数据要素作用的意见》(以下简称《数据二十条》)&#xff0c;以《数据二十条》出台为标志&#xff0c;我国数字经济发展从技术引领进入到数据驱动的新阶段&#xff0c;加快构建数据基础制度&#xf…

LINUX提权之第三方服务提权篇

前言 上一篇文章讲了一下环境变量提权不知道大家学习的怎么样了&#xff0c;今天给大家带来新的提权知识——“第三方服务提权”&#xff0c;本文会深入浅出讲解一下第三方服务提权的原理以及例子。 第三方服务 所谓的第三方服务可以大致理解为系统中安装的软件&#xff08;…

机器人中的数值优化|【二】最速下降法,可行牛顿法的python实现,以Rosenbrock function为例

机器人中的数值优化|【二】最优化方法&#xff1a;最速下降法&#xff0c;可行牛顿法的python实现&#xff0c;以Rosenbrock function为例 在上一节中提到了我们详细探讨了数值优化/最优化理论中的基本概念和性质&#xff0c;现在开始使用python对算法进行实现。上一节链接&am…

CVE-2021-25296 复现

# 漏洞描述 名称&#xff1a;Apache OFBiz rmi反序列化漏洞 cve编号&#xff1a;cve-2021-25296 危害&#xff1a;未授权远程命令执行 影响版本&#xff1a;Apache OFBiz < 17.12.06 OFBiz是一个非常著名的电子商务平台&#xff0c;是一个非常著名的开源项目&#xff0…

Python识别屏幕题目并模拟做题

前言 马上就要过年了&#xff0c;有许多小伙伴们本本还没拿到&#xff0c;还在苦苦刷题&#xff0c;一直及格不了&#xff0c;现在&#xff0c;我们用Python模拟做题&#xff0c;看看效果。 环境使用 python 3.9pycharm 模块使用 requestsreselenium谷歌驱动 import reimpor…