【内存操作】C语言内存函数介绍以及部分模拟实现【初学者保姆级福利】超详细的解释和注释
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语言内存函数介绍以及部分模拟实现【初学者保姆级福利】超详细的解释和注释的更多相关文章
- [原创] Delphi Win API函数 操作帮助文件 HtmlHelpA函数介绍
Delphi Win API函数 操作帮助文件 HtmlHelpA函数介绍 函数原型:HWND HtmlHelpA( HWND hwndCaller, LPCSTR pszFile, UINT uCo ...
- c# 外挂操作(内存操作)(内存读写取窗口句柄移动窗口取模块地址)工具类
来源于网上 参考 https://www.cnblogs.com/fuhua/p/5877781.html 等众多文章 详情取看我第二个例子封装功能较多 https://www.cnblogs.co ...
- C语言学习笔记--内存操作常见错误
1. 野指针 (1)指针变量中的值是非法的内存地址,进而形成野指针 (2)野指针不是 NULL 指针,是指向不可用内存地址的指针 (3)NULL 指针并无危害,很好判断,也很好调试 (4)C 语言中无 ...
- 【Go语言入门系列】Go语言工作目录介绍及命令工具的使用
[Go语言入门系列]前面的文章: [保姆级教程]手把手教你进行Go语言环境安装及相关VSCode配置 [Go语言入门系列](八)Go语言是不是面向对象语言? [Go语言入门系列](九)写这些就是为了搞 ...
- 【保姆级教程】手把手教你进行Go语言环境安装及相关VSCode配置
[Go语言入门系列]前面的文章: [Go语言入门系列](七)如何使用Go的方法? [Go语言入门系列](八)Go语言是不是面向对象语言? [Go语言入门系列](九)写这些就是为了搞懂怎么用接口 本篇文 ...
- C语言 mmap()函数(建立内存映射) 与 munmap()函数(解除内存映射)
mmap将一个文件或者其它对象映射进内存.文件被映射到多个页上,如果文件的大小不是所有页的大小之和, 最后一个页不被使用的空间将会清零.mmap在用户空间映射调用系统中作用很大. 条件 mmap()必 ...
- C语言嵌入式系统编程修炼之三:内存操作
数据指针 在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力.在嵌入式系统的实际调试中,多借助C语言指针所具 ...
- 【C/C++】C语言嵌入式编程修炼·背景篇·软件架构篇·内存操作篇
C 语言嵌入式系统编程修炼之一:背景篇 不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编程语言具备较强的硬件直接操作能力.无疑,汇编语言具备这样的特质.但是,归因于汇编语言 ...
- 【嵌入式开发】裸机引导操作系统和ARM 内存操作 ( DRAM SRAM 类型 简介 | Logical Bank | 内存地址空间介绍 | 内存芯片连接方式 | 内存初始化 | 汇编代码示例 )
[嵌入式开发]ARM 内存操作 ( DRAM SRAM 类型 简介 | Logical Bank | 内存地址空间介绍 | 内存芯片连接方式 | 内存初始化 | 汇编代码示例 ) 一. 内存 ...
- C语言-内存函数的实现(一)之memcpy
C语言中的内存函数有如下这些 memcpy memmove memcmp memset 下面看看memcpy函数 memcpy 我们想想,之前有那个字符串拷贝的函数,即strcpy函数.都有拷贝的函数 ...
随机推荐
- 洛谷P1174 打砖块 | CCPC2021网络赛8.28 1011 动态规划 分组背包
本文学习自洛谷社区 喜提CCPC2021网络赛原题 题意相当于是要在每一列中选若干个砖块打掉,消耗所需的子弹数并得到对应的得分.最大化k个子弹能得到的最大得分. 预处理出第 \(i\) 列 \(j\) ...
- JSONObject--- JSON---与bean对象的转换
1.对象PO转json-string: String json = JSON.toJSONString(customerBueventAccountPO); 1.可能用到的jar宝: json-li ...
- volatile和synchronized和lock的区别
volatile和synchronized的区别: volatile关键字解决的是变量在多个线程之间的可见性(对于用volatile修饰的变量,JVM虚拟机只是保证从主内存加载到线程工作内存的值是最新 ...
- Spring的@Async使用防坑
很多人会直接只用@Async来执行异步操作.但是这里面有一个问题,如果都是用spring的默认实现,是有坑的. 当我们开启 EnableAsync 只有就使用Async来执行异步操作了. 走JDK的动 ...
- C++大整数类
用法 把头文件和源代码文件放在同一目录下,然后#include"INT"即可使用.你能对int类的变量进行a=2,a+=3,a%8,a--等等操作,那你就也能对INT进行.INT基 ...
- 如何使用VNC进行远程桌面控制
VNC是一款很实用的可以实现远程桌面控制的小工具,我遇到的有两种情况比较常见,一是有时候时候可能你会外出或离开自己办公室(但可以访问到办公司的网络),而很多资料都保存在办公室的台式机上,这时如果突然有 ...
- python进度条实现的几种方法
一.普通进度条(time实现) import time def progress_bar(): for i in range(101): print(f'\rProgress: {"#&qu ...
- Nginx Location 深入剖析及动静分离简易配置
本文为博主原创,未经允许不得转载: 1. location 使用分析 location 是 Nginx 配置 中的一个指令,用于访问的 URL 匹配,而在这个 location 中所配置的每个指令将会 ...
- P5728 【深基5.例5】旗鼓相当的对手
1.题目介绍 2.题解 2.1 二维数组 思路 主要熟悉vector创建二维数组的方法 vector<vector> ans(N,vector(3)); 这里第一个元素表明数组大小,第二个 ...
- Linux-文件用户及组管理-chown-chgrp