C语言 内存函数的使用以及部分模拟实现

求个赞求个赞求个赞求个赞 谢谢

先赞后看好习惯 打字不容易,这都是很用心做的,希望得到支持你 大家的点赞和支持对于我来说是一种非常重要的动力 看完之后别忘记关注我哦!️️️

看完这篇博客,除了学会这个几个内存函数之外,相信你会对计算机的内存,以及指针的理解和应用会提高一个层次

强烈建议本篇收藏后食用

memcpy函数

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

函数介绍
图片取自:www.cplusplus.com

该函数可以将内存中固定字节数拷贝到另一块内存空间中
例子:

int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 }; memcpy(arr2,arr1,20);
//将arr1所指向的内存中取20个字节的内容拷贝到arr2中
return 0;
}

我们f10并打开监视就可以看到arr2已经被拷贝了20个字节的结果:1,2,3,4,5.

memcpy的模拟实现

void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
//为了防止dest在后续操作中丢失地址
//我们用一个ret来记录dest一开始的地址
//拷贝完成后我们直接返回ret即可
assert(dest && src);//断言dest和src都不是空指针
int i = 0;
for (i = 0; i < num; i++)
{
*((char*)dest) = *((char*)src);//因为void*类型指针
//不能够解引用,因此强制转化成char*类型,每次拷贝一个字节即可。
dest = (char*)dest + 1;
src = (char*)src + 1;
//每次拷贝完一个字节,拷贝下一个字节,一共拷贝num次
}
return ret;//返回拷贝完的地址
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
int i = 0;
my_memcpy(arr2, arr1, 24);
for (i = 0; i < 6; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}


这样我们就成功拷贝了
注意:这种模拟实现方式是不可以处理重叠的内存的,因为我们一个一个字节拷贝,如果前面的拷贝改变了后面即将要拷贝的内存,就会使得我们得不到想要的答案。

而此时,我们就需要memmove函数,这个函数是可以处理重叠的内存的

memmove函数

图片取自:www.cplusplus.com

int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1 + 2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}

memmove是可以处理重叠的内存的

模拟实现memmove

为了可以处理重叠的内存,我们要分两种情况。
第一种:从前向后拷贝
第二种:从后向前拷贝。

如果我们的src在dest后面我们就必须从后向前拷贝
如果我们的dest在src后面,我们就必须从前向后拷贝。
这样才能使得我们在拷贝内存的时候不会有因为重叠而造成错误的结果。
对于这一部分不明白的伙伴可以给我私信留言。

void*my_memmove(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest && src);
if (dest < src)//判断拷贝方向
{
//从前向后
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
//从后向前
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
//因为这里的num--所以,我们这样写就可以了,每次--交换一次
//直到循环跳出 }
}
return ret;
}

//memcpy-只是先了不重叠的拷贝,而vs中的实现既可以拷贝不重叠,也可以拷贝重叠内存
//vs库里面的memcpy是可以拷贝重叠的,过程和我们写的memmove一样
//但是不保证每一种编译器都可以,所以,我们操作重叠内存的时候,就用memmove就可以了

对于这一部分不明白的伙伴可以给我私信留言。

memcmp函数

图片取自:www.cplusplus.com

内存比较函数
这个函数与strcmp函数十分相似
原型:int memcmp ( const void * ptr1, const void * ptr2, size_t num );
使用过程:

int main()
{
float arr1[] = { 1.0,2.0,3.0,4.0 };
float arr2[] = { 1.0,3.0 };
int ret = memcmp(arr1, arr2, 4);
printf("%d\n", ret);
//返回值和strcmp很相似
return 0;
}

这个函数比较简单,在这里就不给大家模拟实现了,相信你看了上面两个函数的模拟实现过程,模拟实现这个函数不成问题。

memset函数

图片取自:www.cplusplus.com

memset内存设置函数
原型:void * memset ( void * ptr, int value, size_t num );
可以将ptr指向的num个字节的内存设置成想要的值。
使用过程

int main()
{
int arr[10] = { 0 };//前20个字节设置成1
memset(arr,1,20);//以字节为单位设置,每个字节都是1
//01 01 01 01肯定不是1 //如果想把每个元素设计成1,不能用memset
//字符可以
char arr2[10] = { 0 };
memset(arr2, 'a', 5);
printf("%s ", arr2);
return 0;
}

注意,这里得到的结果肯定不会是1的,我们是把20个字节设置成1,不是20个整型设置成1

以上就是这四个函数的全部内容了,非常感谢你能看到这里,别忘了点关注,点收藏,点大拇指,一键三连再走哦!

【内存操作】C语言内存函数介绍以及部分模拟实现【初学者保姆级福利】超详细的解释和注释的更多相关文章

  1. [原创] Delphi Win API函数 操作帮助文件 HtmlHelpA函数介绍

    Delphi Win API函数 操作帮助文件 HtmlHelpA函数介绍 函数原型:HWND HtmlHelpA( HWND hwndCaller, LPCSTR pszFile, UINT uCo ...

  2. c# 外挂操作(内存操作)(内存读写取窗口句柄移动窗口取模块地址)工具类

    来源于网上  参考 https://www.cnblogs.com/fuhua/p/5877781.html 等众多文章 详情取看我第二个例子封装功能较多 https://www.cnblogs.co ...

  3. C语言学习笔记--内存操作常见错误

    1. 野指针 (1)指针变量中的值是非法的内存地址,进而形成野指针 (2)野指针不是 NULL 指针,是指向不可用内存地址的指针 (3)NULL 指针并无危害,很好判断,也很好调试 (4)C 语言中无 ...

  4. 【Go语言入门系列】Go语言工作目录介绍及命令工具的使用

    [Go语言入门系列]前面的文章: [保姆级教程]手把手教你进行Go语言环境安装及相关VSCode配置 [Go语言入门系列](八)Go语言是不是面向对象语言? [Go语言入门系列](九)写这些就是为了搞 ...

  5. 【保姆级教程】手把手教你进行Go语言环境安装及相关VSCode配置

    [Go语言入门系列]前面的文章: [Go语言入门系列](七)如何使用Go的方法? [Go语言入门系列](八)Go语言是不是面向对象语言? [Go语言入门系列](九)写这些就是为了搞懂怎么用接口 本篇文 ...

  6. C语言 mmap()函数(建立内存映射) 与 munmap()函数(解除内存映射)

    mmap将一个文件或者其它对象映射进内存.文件被映射到多个页上,如果文件的大小不是所有页的大小之和, 最后一个页不被使用的空间将会清零.mmap在用户空间映射调用系统中作用很大. 条件 mmap()必 ...

  7. C语言嵌入式系统编程修炼之三:内存操作

    数据指针 在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力.在嵌入式系统的实际调试中,多借助C语言指针所具 ...

  8. 【C/C++】C语言嵌入式编程修炼·背景篇·软件架构篇·内存操作篇

    C 语言嵌入式系统编程修炼之一:背景篇 不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编程语言具备较强的硬件直接操作能力.无疑,汇编语言具备这样的特质.但是,归因于汇编语言 ...

  9. 【嵌入式开发】裸机引导操作系统和ARM 内存操作 ( DRAM SRAM 类型 简介 | Logical Bank | 内存地址空间介绍 | 内存芯片连接方式 | 内存初始化 | 汇编代码示例 )

    [嵌入式开发]ARM 内存操作 ( DRAM SRAM 类型 简介 | Logical Bank | 内存地址空间介绍 | 内存芯片连接方式 | 内存初始化 | 汇编代码示例 )     一. 内存 ...

  10. C语言-内存函数的实现(一)之memcpy

    C语言中的内存函数有如下这些 memcpy memmove memcmp memset 下面看看memcpy函数 memcpy 我们想想,之前有那个字符串拷贝的函数,即strcpy函数.都有拷贝的函数 ...

随机推荐

  1. rabbitMq消息持久化机制,和延时队列

    1.RabbitMQ的一大特色是消息的可靠性,那么它是如何保证消息可靠性的呢? 消息持久化.可以将Queue,Exchange,Message都设置为可持久化的.为了保证RabbitMQ在退出,服务重 ...

  2. 从运维域看 Serverless 真的就是万能银弹吗?

    作者说 ​ 在开始本篇内容前我想与各位开发者达成几个共识. ​ 第一个共识,软件工程没有银弹, Serverless 也不是银弹,它并不是解决所有问题的万能公式. 第二个共识,Serverless 能 ...

  3. [TSG@Site开发日志3]从C#到Qt,再从Qt到C# 和 Qt的组合开发,浅谈在采集端工控设备开发中不同技术之间选型的利与弊

    [TSG开发日志3]从C#到Qt,再从Qt到C#,浅谈不同技术之间选型的利与弊 当前在South公司的开发历经了几个时代,第一个时代是用C#进行的开发,第二个时代是从C#向Qt逐渐转型,第三个时代是我 ...

  4. C#将汉字转换为拼音

    首先上效果图 方法调用 private void txt_Chinese_TextChanged(object sender, EventArgs e) { txt_PinYIn.Text = //调 ...

  5. 扒一扒ProcessOn 新功能——一键编号、图形组合、左侧导航、画布水印、表格组件

    思维导图.一键编号 思维导图新增 多种全新主题风格,让您的创作赏心悦目 思维导图新增 一键编号 功能 流程图.图形组合 自定义组合图形功能:新增流程图 我的图形 功能,用户可以设置或者上传自己的图形 ...

  6. java基础-常用类-day11

    目录 1. 包装类 2. Integer类 3.util.date 4. java.sql.Date 5. SimpleDateFormat 6. Calendar 7. Math 8. String ...

  7. 理解 docker volume

    1. docker volume 简介 文章 介绍了 docker image,它由一系列只读层构成,通过 docker image 可以提高镜像构建,存储和分发的效率,节省时间和存储空间.然而 do ...

  8. 基于java+springboot的图书借阅网站-在线图书借阅管理系统

    该系统是基于java+springboot开发的图书借阅管理系统.是给师弟开发的课程作业.大家学习过程中,遇到问题可以github咨询作者. 系统演示地址 前台 http://book.gitapp. ...

  9. [转帖]Linux命令(51)——ipcs命令

    https://cloud.tencent.com/developer/article/1380589 1.命令简介 ipcs命令用于报告Linux中进程间通信设施的状态,显示的信息包括消息列表.共享 ...

  10. 【转帖】JVM 元数据区的内存泄漏之谜

    https://www.infoq.cn/article/Z111FLot92PD1ZP3sbrS 一.问题描述 某天,SRE 部门观察到一个非常重要的应用里面有一台服务器的业务处理时间(Transa ...