【C语言进阶篇】C语言内存函数

这篇具有很好参考价值的文章主要介绍了【C语言进阶篇】C语言内存函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【C语言进阶篇】C语言内存函数

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

 🌈个人主页:开敲

🔥所属专栏:C语言

🌼文章目录🌼

1.memcpy函数及其模拟实现

    1.1 memcpy函数的使用

    1.2 memcpy函数的模拟实现

2.memmove函数及其模拟实现

    2.1 memmove函数的使用

    2.2 memmove函数的模拟实现

3.memset函数

4.memcmp函数

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

1.memcpy函数及其模拟实现
    1.1 memcpy函数的使用

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

  memcpy函数是用来拷贝内存的函数,其拷贝的方式为一个字节一个字节地拷贝,使用时需要包含 <string.h> 的头文件。上面的 size_t num 参数的作用就是接收我们输入的想要拷贝的字节数;destination的意思是目的地,void* destination 参数是拷贝存放的目的地;source是起源的意思,const void* source就是我们所要拷贝的数据的起始地。两个接收地址的变量用 void* 类型来定义,说明可以接收不同类型的地址。来看看具体使用:

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

  这里我们将 arr 数组里20个字节的内存拷贝到 arr1 数组中去,因为arr数组的类型为int型,每个元素的大小为4个字节,因此,拷贝20个字节的内容相当于拷贝了 arr 中5个元素进 arr1 中。

  需要注意的是,如果 arr1 数组中本身有元素,在拷贝的时候,拷贝过去的元素会覆盖掉 arr1 中原有的元素:

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

  操作字符串:

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

    1.2 memcpy函数的模拟实现

  下面我们来自己动手模拟实现一下memcpy函数:

//模拟实现memcpy函数
void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	//这一步是为了保存dest最开始指向的地址,因为在后续循环里的操作里,
	//dest的地址已经跑到后面去了,不指向最开始的地址

	while (num--)//这里是总共循环的次数,需要拷贝多少个字节就循环多少次
	{
		*(char*)dest = *(char*)src;

		// 因为dest与src都是void*类型,没法直接解引用操作,又因为
		// memcpy函数是一个字节一个字节拷贝的,因此我们在这进行拷贝操作的时候
		//将dest与src都强制类型转换为char*类型,这样就可以达到一个字节一个字节拷贝的目的了

		dest = (char*)dest + 1;
		src = (char*)src + 1;

		//这里的操作是在拷贝完一个字节以后,dest与src的地址都+1
		//去找下一个字节地址,进行下一个字节的拷贝

	}
	return ret;
}


int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr1[10] = { 0 };
	my_memcpy(arr1, arr, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}
2.memmove函数及其模拟实现
    2.1 memmove函数的使用

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

  memmove函数的作用和memcpy函数几乎一样,使用时也需要包含<string.h>的头文件但是memcpy函数相比于memmove函数来讲有一个缺陷,下面来看一段代码:
【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

这里我们想要将 arr 数组中 1,2,3,4,5 的数据拷贝到 arr 数组中 3,4,5,6,7 的位置,那么结果按理来说应该最后输出打印的是 1,2,1,2,3,4,5,8,9,10。但实际上跟我们想的一样吗?

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

没错,想的和我们就是一样的,可能这个时候就有人想说我在水字数了。哎!此言差矣。虽然在这里最后输出的结果和我们设想的是一样的,但是,这仅是在VS编译器环境下一样而已,换做别的编译器,可能最后输出的就是下列结果:

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

为什么可能输出这个结果呢?我们来画图理解:

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

那么我们如果想要在一个数组里实现我们想要的效果,该怎么办呢?

  这就需要用到memmove函数了,memmove函数就可以专门用来处理这种拷贝内存与存放内存有重叠的情况:

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

在VS编译器中,memcpy函数也能够完成memmove的作用,我们不妨大胆猜测,在VS中memcpy函数的实现是和memmove函数一样的。

    2.2 memmove函数的模拟实现

  下面我们来手动模拟实现一下memmove函数。

  在模拟实现memmove函数之前,我们需要搞清楚memmove函数的原理,memmove函数的模拟实现相较于memcpy函数更为复杂,我们来逐个讨论:
 

  如何避免在拷贝内存的时候将后面需要拷贝的内存给改变呢?就像上面所说的改为 1,2,1,2,1,2,1,8,9,10 的情况。这时候我们可以想到,将内存从后往前拷贝不就行了,就像这样:

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

  ② 

  用从前往后的方法就可以达到我们上面的目的,但是,这里又会出现一个新的问题,如果我需要拷贝的内存在存放的内存后面呢,就像下面这种情况:

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

  这种情况从前往后存还适用吗?我们画图来探究一下:
  【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

  显然,这个时候再采用从后往前的方法就不行了。既然从前往后不行,那我们从前往后可行吗?画图探究下:

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

可以发现,这种情况从前往后拷贝存储是可行的,那么除了这两种情况还有别的情况吗?没有了,需要拷贝的内存拷贝内存目的地重复的情况一共就三种:  ① 需要拷贝的内存拷贝内存目的地前并且两者有重复部分   ② 需要拷贝的内存拷贝内存目的地后并且两者有重复部分  ③ 两者完全重复 。而第三种情况不管怎么拷贝都能达到我们的目的,因此,在模拟实现memmove函数时,我们只需要考虑前两种情况即可。下面来看代码:

  

void* my_memmove(void* dest, const void* src, size_t num)
{
		if (dest > src)//拷贝内存在拷贝存放的内存的前面,并且有内存叠加
		{
			dest = (char*)dest + num - 1;//将dest和src分别指向各自的最后一个字节
			src = (char*)src + num - 1;
			while (num--)//将内容一个字节一个字节进行拷贝
			{
				*(char*)dest = *(char*)src;
				dest = (char*)dest - 1;
				src = (char*)src - 1;
			}
		}
		else
		{
			while (num--)//拷贝内存在拷贝存放的内存的后面,并且有内存叠加
			{
				*(char*)dest = *(char*)src;//直接从第一个字节拷贝
				dest = (char*)dest + 1;
				src = (char*)src + 1;
			}
		}
}

int main()
{
	int arr[] = { 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;
}
3.memset函数

  memset函数顾名思义就是用来设置内存,将需要设置的内存中的值按照字节来设置成想要的内容,使用时也需要包含<string.h>的头文件

  【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

这里我们用memset函数将字符串s的前三个字节的内容改为了字符 ' x '。 

4.memcmp函数

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

memcmp函数是用来比较内存的,用法与strcmp函数十分相似,不同的是,strcmp函数是专门用来比较字符串的函数,而memcmp函数则可以用来比较各种类型。

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

这里的意思就是:当所比较的两个字符串,前一个大于后一个则返回一个大于0的数,反之则返回小于0的数,相等则返回0

【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言

这里我们调用的memcmp的时候,将 与 s1 进行比较,如果 s1 ,则返回一个大于0的数,反之,则返回小于0的数,如果相等,则返回0。这里 的第一个字符是a,而 s1 的第一个字符是b,在第一个字符就判断出了大小,后面也不用判断了,直接返回了小于0的数。

                                                       创作不易,点个赞再走呗,求求啦~😊

               【C语言进阶篇】C语言内存函数,C语言,c语言,开发语言文章来源地址https://www.toymoban.com/news/detail-850680.html

到了这里,关于【C语言进阶篇】C语言内存函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言进阶】C语言动态内存管理

    今天学习了C语言进阶部分中的动态内存管理,现在图书馆要关门了,在这里浅谈一下与动态内存管理有关的三个函数。更详细的剖析我会在日后更新~ C语言动态内存管理是程序员必须掌握的重要技能之一,它可以使程序在运行时动态地分配和释放内存。C语言提供了几个函数

    2023年04月08日
    浏览(46)
  • 【C语言】进阶——动态内存管理

    我们已经掌握的内存开辟方式有: 但上述开辟空间的方式有两个 特点: 空间开辟 大小 是固定的 数组在声明的时候,必须指定 数组的长度 ,他需要内存在 编译时分配 对于空间的需求,不仅仅是上述的情况,有时候我们需要的空间大小在程序运行的时候才知道,那数组的编

    2024年02月06日
    浏览(50)
  • 【进阶C语言】动态内存管理

    前言 📕作者简介: 热爱跑步的恒川 ,致力于 C/C++、Java、Python 等多编程语言,热爱跑步,喜爱音乐的一位博主。 📗本文收录于 C语言进阶 系列,本专栏主要内容为数据的存储、指针的进阶、字符串和内存函数的介绍、自定义类型结构、动态内存管理、文件操作等,持续更

    2023年04月18日
    浏览(41)
  • 进阶C语言-动态内存管理

    ✅截止目前,我们掌握的内存开辟的方式有: 但是上述的开辟空间的方式有两个特点: 空间开辟的大小是固定的。 数组在申明的时候,必须指定数组的长度,它所需的内存在编译时分配。 🔎但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运

    2024年02月21日
    浏览(49)
  • 【进阶C语言】动态内存分配

    本章大致内容介绍: 1.malloc函数和free函数 2.calloc函数 3.realloc函数 4.常见错误案例 5.笔试题详解 6.柔性数组 1.malloc函数 (1)函数原型 函数参数: 根据用户的需求需要开辟多大的字节空间,为无符号的字节。 返回值: malloc函数成功开辟内存后,会返回该内存的起始地址,可

    2024年02月07日
    浏览(54)
  • 【再识C进阶3(下)】详细地认识字符分类函数,字符转换函数和内存函数

    💓作者简介: 加油,旭杏,目前大二,正在学习 C++ , 数据结构 等👀 💓作者主页:加油,旭杏的主页👀 ⏩本文收录在:再识C进阶的专栏👀 🚚代码仓库:旭日东升 1👀 🌹欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖        在上一篇博客中,我们学习了字符串函数,字

    2024年02月08日
    浏览(38)
  • 动态内存管理——C语言【进阶】(下)

    作者简介: 辭七七,目前大一,正在学习C/C++,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: 进阶C语言,本专栏主要讲解数据存储,进阶指针,动态内存管理,文件操作,程序环境和预处理等 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖 请问运行Test 函数会有什

    2023年04月18日
    浏览(90)
  • 动态内存管理——C语言【进阶】(上)

    我们已经掌握的内存开辟方式有: 但是上述的开辟空间的方式有两个特点: 空间开辟大小是固定的。 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。 但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知

    2023年04月10日
    浏览(42)
  • 动态内存管理(C语言进阶版)

    📙 作者简介 :RO-BERRY 📗 学习方向:致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识 📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持 现在的偷懒会在以后还给你,只有多学多做才不负韶华,在默默无闻的地方发芽开花 我们已经掌握的

    2024年02月13日
    浏览(44)
  • 【C语言进阶(八)】动态内存管理

    💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C语言学习分享⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习更多C语言知识   🔝🔝 本章目标: 本篇文章 着重讲解动态内存 管理的四个函数 前期准备: 内存可以大致分为几个区域: 栈区: 存放局部变量,函数 堆区

    2024年02月16日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包