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. 路径规划之 A* 算法

    算法介绍 A*(念做:A Star)算法是一种很常用的路径查找和图形遍历算法.它有较好的性能和准确度.本文在讲解算法的同时也会提供Python语言的代码实现,并会借助matplotlib库动态的展示算 ...

  2. 【每日一题】36. 小AA的数列 (二进制DP)

    补题链接:Here 算法涉及:位运算,DP 这道题想了很久但实在没想什么巧妙的解法,暴力的代码就不放,这里引用Kur1su 的思路 异或问题优先考虑二进制位,对于这个问题,我们需要考虑偶数长度的区间, ...

  3. java编译期和运行期和string原理

     编译期:   是指把源码交给编译器编译成计算机可以执行的文件的过程.在Java中也就是把Java代码编成class文件的过程.编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码 ...

  4. Django 对实体的增删改查样例

    class UserInfo(models.Model): """ 人员信息 """ user_id = models.CharField( ...

  5. MySQL驱动扯后腿?Spring Boot用虚拟线程可能比用物理线程还差

    之前已经分享过多篇关于Spring Boot中使用Java 21新特性虚拟线程的性能测试案例: Spring Boot 3.2虚拟线程搭建静态文件服务器有多快? Spring Boot 虚拟线程与We ...

  6. MaxListenersExceededWarning:Possible EventEmitter memory leak detected.

    打包出现内存溢出 解决办法:

  7. hdu 5547

    ***题意:4*4数独,要求在同一行同一列不能有相同的数字,另外在2*2的小单元里也不能有相同的数字 思路:DFS暴力搜索, 每个位置填1-4,递归回溯,判断是否符合条件,递归到最后一个位置+1则输出 ...

  8. PR 调整时间线宽度

    1.问题 这里的宽度太小,不好进行下一步的调整 2.解决方法 方法一 按下=可以放宽 按下-(=左边的那个键)可以缩小宽度 方法二 拖动下方的滑动条即可 方法三 按住ALT+滚轮,即可调节

  9. 【Linux】技术收集

    Linux进程间通信(六)---信号量通信之semget().semctl().semop()及其基础实验 https://blog.csdn.net/mybelief321/article/deta ...

  10. 【TouchGFX】Widgets and Containers

    Widgets and Containers 是 TouchGFX 应用最基础的东西,他们贯穿于 UI 的整个开发,属于 TouchGFX 的预制组件,同时也支持自定义实现 Widgets Widge ...