欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > C语言中的内存函数

C语言中的内存函数

2024/10/24 16:55:54 来源:https://blog.csdn.net/Dove_Xxx/article/details/143096975  浏览:    关键词:C语言中的内存函数

字符函数和字符串函数的章节结束了,接下来我们进入到C语言中的内存函数

今天的主角有:memcpy 函数、memmove 函数、memset 函数、memcmp 函数

一 . memcpy 函数

(1)memcpy 函数的使用 

这个 memcpy 函数是专用于内存拷贝的,大家是不是觉得很熟悉,我们才刚刚学习过用于拷贝的函数 —— strcpy 函数和 strncpy 函数,那么它们之间有着怎样的区别呢?

我们之前学习的 strcpy 函数、strncpy 函数是专用于字符串之间拷贝字符的,那么今天我们将要学习的 memcpy 函数诸君看到标题也能知道这个是用于内存拷贝的,它是不仅仅局限于拷贝字符串的,而是所有类型都能拷贝,并且,它可没有什么 memncpy,它本身就能对我们拷贝的元素个数进行限制

(1 . 1)对字符串的拷贝:

(1 . 2)对整型的拷贝:

如上图所示,我们的 memcpy 函数的运用还是相当简单的,有着前两期对这一系列函数的讲解,我相信聪明的诸君理解起来都是非常之简单的,轻松拿捏。如果是没有看过前两期的小伙伴,我建议还是可以去看一看的,能够帮助理解

(2)memcpy 函数的模拟实现

咱们这里直接以整型为例:

(2 . 1)使用 if 循环:

看过前两期的朋友我无需多言,在我们的 My_memcpy 内就是进行的一个简单的赋值、前进再循环

大家可以注意到,我们原 memcpy 函数的格式:

它的接收参数和返回值都是 void * 类型的,我们虽然是用整型举例,但我们实质还是模拟实现 memcpy 函数,我们不能只用整型,也得遵循 void * 类型的接收返回,我们这里虽然是整型类型,但是朋友们请注意了,我们在赋值时用的是 char * 的强转,为什么不用 int * 强转呢?这是因为我们这里需要拷贝给的正好是 20 个字节长度,但如果我给你 17 个字节呢?4 次拷贝结束,剩下的 1 个字节如何处理呢?所以我们选用 char * 类型一个字节一个字节的拷贝是一种更加严谨的操作

我们这个:dest = (char*)dest + 1 为什么不写成:(char*)dest ++ 呢?直接一步到位,这一次我们为什么要用这样 “ 原始 ” 的方式呢?因为我们的强转是一种临时操作,在我们强转之后在解引用的时候,dest 已经不是(char*)的类型了,它依旧是(void*)类型。这个时候有同学要问了,那这样呢:++(char*)dest,这种前置 ++ 是会优先运算的,这个 ++ 的时候我们 dest 还是(char*)的类型,但是这样的方式看似可行,是强转后的马上++,但是这样的方法不能保证在所有的编译器上正确运行的。所以我们只能返璞归真,用这种形式

(2 . 2)使用 while 循环:

while 循环我们直接用 num -- 作为循环条件,直至 num 为 0 自动跳出循环,这一点相信诸君不难理解吧 

一 . 一 . memcpy 函数不能用于重叠的内存拷贝

什么叫重叠的内存拷贝呢?如下:

具体解析咱们文字不好说,我用画图的方式给大家呈现:

诸君可以看到,当我们拷贝对象和地址有部分重叠时,当我们需要把 “ 3 ” 拷贝到 “ 5 ” 这个位置的是偶,我们的 “ 3 ” 已经不是 3 了,这个时候它已经被 1 替换掉了

有的同学坚信实践是检验真理的唯一标准昂,自己去试了一下发现没有问题啊,怎么这样说呢,那是因为我们特殊的编译环境,VS上的库函数 memcpy 也能实现重叠内存的拷贝,但并不是所有编译器上都能实现,可能在其他编译器就跑不动了呢?在我们C语言的标准规定中是定义memcpy 函数不负责重叠内存的拷贝,非要使用的话,结果是未定义的,所以我们尽量避免用memcpy 函数去进行重叠内存的拷贝,咱们术业有专攻,进行重叠内存拷贝的角色另有人选,那就是我们接下来即将登场的 memmove 函数!

二 . memmove 函数

(1)memmove 函数的使用  

memmove 函数的使用格式跟我们之前讲的一系列函数大差不差,没啥新知识点,咱们多的不说少的不唠,直接演示:

大家看,这一个 memmove 函数就能完美执行我们重叠内存的拷贝,这个没有什么好说的点,咱们直接进入下一环节了昂

(1)memmove 函数的模拟实现  

解析:memmove 函数的模拟实现有很重要的点,因为我们并不了解 memmove 函数实现的底层逻辑,我们不可能直接一步到位去实现对重叠内存的拷贝,但是我们可以多思考一下,采用逆向思维:当我们需要拷贝的地址在拷贝对象之后我们的内存会被拷贝时覆盖,那我们不妨试试从后往前拷贝,这样子就能巧妙地避开我们被拷贝覆盖的内存

文字不太好理解,我来在图上为诸君解析:

如图所示,我们可以看到我所列举的两种情况:

(1 . 1)情景一:dest 在 sour 之后

这个时候我们从前往后进行拷贝,就会遇到我们使用 memcpy 函数进行重叠内存拷贝时的问题,我再把那张图拿下来大家看一下:

 此时我们如果还是执迷不悟依旧要使用从前往后的常规拷贝方式,那么我们的内容一定会被覆盖掉,所以我们应当选择逆向思维从后往前拷贝,大家可以发现此时从后往前就可以很巧妙的避开拷贝时的重叠元素:5 -> 7,4 -> 6,3 -> 5,2 -> 4,1 -> 3

(1 . 2)情景二:dest 在 sour 之前

当我们的拷贝地址在拷贝对象之前的这种情景,我们会发现此时的从后往前拷贝会使我们的重叠内容被覆盖,所以我们在 dest 在 sour 之前的这种情况还是选择从前往后拷贝,这样子我们的内容就不会被覆盖了

三 . memset 函数

memset 函数的使用

如图,我们的 memset 函数是专用于修改字符串中单个字符的函数

memset 函数中有着三个参数,分别是什么含义呢?

void * ptr:我们要修改的字符串中字符的起始地址

int value:修改的目标字符(将原字符改成什么字符,注意:只能修改成单一字符) 

size_t:修改字符的个数(注意:只能连续修改字符

使用格式非常简单,如下图:

四 . memcmp 函数

memcmp 函数的使用

大家是不是觉得有点眼熟哇,之前我们学到过 strcmp 函数和 strncmp 函数,这俩是专用于字符串大小的比较,比较的是对应字符的ASCLL码值的大小是吧,这个 memcmp 函数是用于比较内存中字节块的大小,不仅仅局限于字符串,并且呢它没有 memncmp 的形式,也是自带对比个数限制的

返回值:这个返回值跟我们的 strcmp 函数和 strncmp 函数的C语言规定是一模一样的:

ptr1 > ptr2 返回大于 0 的数;ptr1 < ptr2 返回小于 0 的数;相等则返回 0

(同样,在我们的 VS 中相对应的也只会返回 1、- 1、0,其他编译器可能会有所不对)

(1)整型间的比较:

(2)字符间的比较:

这个 memcmp 函数还是相当简单的,没啥难点,都是我们学过的老朋友了昂,我觉得也不用给诸君过多赘述了,就这样吧,如果有小伙伴有所疑问的话,欢迎在评论区和私信跟我讨论哦

OKK,有关C语言中的内存函数的章节我们就到此为止啦。诸君动动发财的小手,如果此篇文章对你有所帮助的话,不妨点点赞点点关注噢!就这样吧,咱们下期再见!与诸君共勉!!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com