首页 > 系统相关 >《内存函数》

《内存函数》

时间:2024-11-13 23:44:18浏览次数:3  
标签:函数 memmove 内存 拷贝 memcpy 指针

内存函数

1. memcpy函数

(1)介绍

在这里插入图片描述
这里通过memcpy的定义我们可以看这个函数包含三个参数,destination就是拷贝的目的地,source就是拷贝的源头,num就是拷贝的个数。

(2)使用

在这里插入图片描述

  1. 这里要包含头文件string.h
  2. 这里的个数最好写成sizeof(类型)* 个数的形式,因为你拷贝什么类型未定

(3)memcpy 函数模拟实现

在这里插入图片描述
思路整理: 通过对memcpy的学习,我们知道了这是一个用来拷贝数据的函数,并且它本身并不care它要拷贝的数据是什么类型的,所以这里我们传参的时候就要写成void* 的指针,和原函数保持一致,由于我们要用这个函数来实现所有类型数据的拷贝,所以用char*类型的指针来逐个字节进行交换最合适不过了,但void* 的指针不能直接进行解引用,要进行强转,然后在逐个字节进行交换时,两个指针要往后走,至于走到哪,这里就拿while循环来判断,将num作为循环判断条件,当num为0时交换完成,循环正好停止,但是因为强转类型是是临时的,所以这里直接让指针++就不行,还要再次进行强转才可以,这里是比较容易忽视的一个点。并且这个函数还要返回目的地的地址,并且是void*类型的,但是直接在结尾返回dest是有问题的,因为在进行了一系列循环后,指针早就跑远了,这时候我们就可以在开头就先把这个地址传给另一个指针ret,最后在结尾返回指针ret就可以了,这时候这个函数就比较完善了,但因为这里用到了指针,所以在使用之前其实可以先判断一下是否为空指针,这时候就用到了assert,加上这个的话函数就更加健壮了。

(4)局限性

其实C语言中规定memcpy函数不用来拷贝重叠内存,但我们还是来测试一下
首先我们用自己模拟的my_memcpy来测试一下

在这里插入图片描述
显然这里我们可以发现用我们自己模拟的my_memcpy函数拷贝重叠内存时发生了错误,我们可以借助下图来进行理解
在这里插入图片描述
我们通过逐个字节来交换来进行拷贝,但比如这里的源头在该取3来进行交换时,这时候其实3已经被1给覆盖了,也就是说这时候你取出的不是3,而是1,所以这时候就出错了啊。

既然我们自己模拟的my_memcpy不能完成这个任务,那么库函数中的memcpy应该也不行吧,下面我们来试一下

在这里插入图片描述
到这里有些同学可能就坐不住了,这memcpy不是说不能拷贝重叠内存的吗?这里为什么还是可以啊,其实不然,这只是在部分编译器中可以实现,但你不能保证它在任何情况下都可以做得到的,并且我们有专门的函数来实现这个功能,所以不建议用memcpy这样干。

2.memmove函数

(1) 介绍

在这里插入图片描述
这里通过memmove的定义我们可以发现这个函数也是有三个参数,包括目的地、源头、拷贝个数

(2)使用

在这里插入图片描述

这里我们看到memmove函数不仅可以实现重叠内存的拷贝,而且也可以实现不相关两组数据的拷贝。

(3)memmove函数模拟实现

在这里插入图片描述
思路整理: 通过对memmove函数的学习,我们发现这个函数是既可以实现重叠内存的拷贝,也可以实现不相关内存的拷贝,这时候我们在实现这个函数的时候就需要分情况来思考了,我们通过下面这个图来理解:
在这里插入图片描述

  1. 情况1的时候如果还是先从源头开始拷贝的话就会出现一种现象:在拷贝3的时候,这个3已经被1给覆盖住了,你拿到的不是3而是1,这就出错了啊,所以这个时候我们就需要从末尾开始拷贝,从源头的末尾开始拷贝,依次放到目的地的末尾,这样就可以正确拷贝了
  2. 情况2的话是目的地在在源头左边,这个时候就可以从源头开头依次进行拷贝,也就是和上面的my_memcpy道理一样。
    3.情况三不属于重叠内存的拷贝,无论是从左还是从右拷贝都可以
  3. 既然这样话,我们可以以dest和src的位置来划定情况,当dest在src左边时从左开始拷贝,其他两种情况从右开始拷贝。

这里其实还需要进行解释的一点是在从右开始拷贝的时候怎么找到src和dest的末尾,这里我们通过(char*)dest + num (char*)src + num 分别找到了destsrc的末尾,接着我们通过while循环,并且以num-- 作为循环判断条件,这时候随着num的变化,指向destsrc的指针也跟着移动,从右向左进行交换,当num为0时,交换完成,循环停止。

(4)memcpy和对比memmove对比

综上所述:memmove函数的作用>> memcpy的作用,memcpy能做的memmove可以做,memcpy做不了的memmove也能做。

3. memset函数

(1)介绍:

在这里插入图片描述
通过memset的定义我们可以看到这个函数包含了三个参数
在这里插入图片描述
一般情况下这个函数可以用来内存的初始化、清空数组、给特殊值

(2)使用

在这里插入图片描述

这个函数比较简单就不再过多介绍。

4. memcmp函数

(1)介绍

在这里插入图片描述
在这里插入图片描述

(2)使用

在这里插入图片描述
注意这里比较的是内存中的大小。

5.总结

这期我们主要学习了memcpy函数、memmove函数及两个函数的模拟实现、memset函数和memcmp函数。这期中比较难一点理解的就是memmove函数的模拟实现,大家可以反复翻看,加深理解,注意体会其中的思想。

标签:函数,memmove,内存,拷贝,memcpy,指针
From: https://blog.csdn.net/2401_87465145/article/details/143753555

相关文章

  • 在Clion中快速生成函数中形参注释及添加函数说明
    快速生成函数中形参注释只需要在函数前输入/**,然后按回车,这样即可快速生成如下函数形参注释。 新增函数描述在设置界面中的搜索框中输入CodeGeneration,然后勾选如下选择框,这样就可以在如上生成的代码快中新增函数描述栏 说明:有些版本可能找不到,按如下位置查找即可。......
  • 深度学习 PyTorch 中的 logits 和交叉熵损失函数
    在深度学习中,理解损失函数是训练模型的关键一步。在分类任务中,交叉熵损失函数是最常用的损失函数之一。本文将详细解释PyTorch中的logits、交叉熵损失函数的工作原理,并展示如何调整张量的形状以确保计算正确的损失。什么是logits?logits是模型输出的未归一化预测值,通常......
  • STL容器的各个函数方法
    std::vectorstd::vector是一个动态数组,支持随机访问。push_back(value):在末尾添加一个元素。pop_back():移除末尾的元素。size():返回容器中的元素数量。empty():检查容器是否为空。at(index):访问指定位置的元素,带边界检查。front():返回第一个元素。back():返回最后一个元......
  • 【Azure App Service】在App Service for Windows上验证能占用的内存最大值
    问题描述在创建AppService服务的时候,根据定价层不同,内存使用的最大值也有不同。但在实际测试中,发现内存最大只能占用2GB左右,而定价层中内存分配明明是大于2GB(比如B3定价层的内存为7GB),这是一种什么情况呢?在AppService中Kudu工具上,查看进程分配的内存大小: 问题解答使......
  • Go语言函数
    函数入门简单精通难函数式编程1、什么是函数函数就是一段代码的集合go语言中至少要有一个main函数函数需要有一个名字,独立定义的情况下。见名知意函数可能需要有一个结果,也可能没有funcprint(){ fmt.Println("hello")}packagemainimport"fmt"funcmain(){......
  • 二分查找(折半查找)函数与非函数写法代码介绍及其优缺点 C语言
    什么是二分查找?二分查找也叫折半查找 在有序的数组中查找目标的方法需要借助中间元素与目标值的比较来逐步缩小范围一直到找到目标元素或者不存在为止查找的步骤↓1确定左右端点的下标值(注:数组下标从0开始)2计算中间下标位置3比较中间下标位置的数组值与目标值的大......
  • C++ 移动构造和拷贝构造函数匹配
    既有拷贝构造又有移动构造这个比较好理解,普通的函数匹配规则就可以。右值移动,左值拷贝。——《C++Primer》P477我们不能隐式地将一个右值引用绑定到一个左值。有拷贝构造但没有移动构造这种情况,右值也会被拷贝。如果一个类没有移动构造函数,函数匹配规则保证该类型的对象......
  • Flink调优之前,必须先看懂的TaskManager内存模型
    Flink调优之前,必须先看懂的TaskManager内存模型TaskManager内存模型Flink的程序运行在内存中。不管是我们在学习C语言、Java语言的时候,我们都很想知道程序到底是如何管理内存的。Flink程序也一样,当我们写完Flink程序,我们需要为Flink程序分配运行的资源,那针对什么样的数据量,需要......
  • 多项式乘幂函数之和 2
    H4.2.1.8.多项式乘幂函数之和2\(n,k\)都是给定数,没什么区别记\(S_k=\sum_{i=1}^ni^kp^i\)\(p=1\)时\(S_k\in\Theta(n^{k+1})\)\(p<1\)时\[\begin{aligned}(1-p)S_k&=\sum_{i=1}^n\left(i^k-(i-1)^k\right)p^i-n^kp^{n+1}\\&=\sum_{i=1}^n\left(......
  • javaScript对象函数初相识
    1.1、对象初相识1.1.1、对象的初识1.1.1.1、对象的定义现实生活中,万物皆对象,对象是一个具体的事物,看得见摸得着的实物。例如一本书,一辆汽车,一个人可以是“对象”,一个数据库,一张网页,一个与远程服务器的连接也可以是“对象”。例子:明星、女朋友、班主任、苹果、手机周星驰......