动态内存的开辟
🐶博主主页:@ᰔᩚ. 一怀明月ꦿ
❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++
🔥座右铭:“不要等到什么都没有了,才下定决心去做”
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
🐰动态内存管理
🐰malloc
🐰calloc
🐰realloc
🐰free
🐰动态开辟常见的错误
🐰动态内存管理
其实我们创建数组的时候,系统为我们就是开辟了一段连续的空间(这个空间一般是在栈区开辟的),现在我们可以自己开辟一段空间。与动态开辟相关的函数:malloc free calloc realloc
注意:数组离开作用域时,系统会自动释放这段空间,如果我们自己动态开辟的空间,离开作用域时,系统是不会帮我们释放这段空间的,如果要求释放这段动态开辟的空间,我们就需要使用free函数去释放。
🐰malloc
malloc用于动态开辟内存,引用的头文件是#include<stdlib.h>
malloc的原型:
void* malloc (size_t size);
size_t size:开辟的字节数
注意:返回的类型是void*类型,如果想要使用这段空间,就必须强制性转化为自己想使用的类型,例如:int* p=(int*)malloc(20);这就是开辟了20个字节,然后把20个字节空间的首地址赋值给了p。
malloc的使用:
malloc开辟成功会返回开辟好的空间的首地址, malloc如果申请内存失败会返回空指针NULL,所以我们开辟好空间的话,需要去判断一下
#include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> int main() {int *p=(int *)malloc(20);//开辟了20个字节的空间if(p==NULL){printf("%s\n",strerror(errno));//打印开辟失败的原因}free(p);p=NULL;return 0; }
malloc开辟空间,不初始化,里面存放的随机值
#include<stdio.h> #include<stdlib.h> int main() {int *p=(int *)malloc(20);//开辟了20个字节的空间for(int i=0;i<5;i++){printf("%d ",*(p+i));}//使用for(int i=0;i<5;i++){*(p+i)=i+1;}for(int i=0;i<5;i++){printf("%d ",*(p+i));}free(p);p=NULL;return 0; }
🐰calloc
calloc用于动态开辟内存,区别于malloc的是,calloc会初始化开辟的空间,将开辟的空间全部初始化为0,引用的头文件是#include<stdlib.h>
calloc的原型:
void* calloc (size_t num, size_t size);
size_t num:开辟的个数
size_t size:开辟的类型的大小
注意:返回的类型是void*类型,如果想要使用这段空间,就必须强制性转化为自己想使用的类型,例如:int* p=(int*)calloc(20,sizeof(int));这就是开辟了20个整形的空间,然后把20个整形空间的首地址赋值给了p。
calloc的使用:
calloc开辟空间,初始化,里面存放的0
#include<stdio.h> #include<stdlib.h> int main() {int *p=(int *)calloc(20,sizeof(int));//开辟了20个int类型的空间for(int i=0;i<20;i++){printf("%d ",*(p+i));}free(p);p=NULL;return 0; }
🐰realloc
realloc用于原空间不足继续开辟更大的空间,引用头文件为#include<stdlib.h>
realloc的原型:
void* realloc (void* ptr, size_t size);
void* ptr:原空间的首地址
size_t size:开辟新空间的大小
注意:realloc开辟空间会遇到两种情况
1.如果原空间后面空间充足
在原空间后面继续开辟空间(返回的地址与原来的地址相同)
2.如果原空间后面空间不足
(1)realloc会找更大的空间
(2)将原来的数据拷贝到新空间
(3)释放原来的旧的空间
(4)返回新空间的地址(返回的地址与原来的地址不同)
realloc的使用:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> int main() {int *p=(int *)malloc(20);//开辟了20个int类型的空间if(p==NULL){printf("%s\n",strerror(errno));}for(int i=0;i<5;i++){printf("%d ",*(p+i));}int* pc=(int*)realloc(p,sizeof(p)*2);//在原空间进行扩展if(pc!=NULL){p=pc;//把空间首地址还是赋给pfor(int i=0;i<10;i++){printf("%d ",*(p+i));}}else{printf("realloc:%s\n",strerror(errno));//如果开辟失败,打印原因}free(p);p=NULL;return 0; }
🐰free
free用于释放动态开辟的空间,引用头文件#include<stdlib.h>
free的原型:
void free (void* ptr);
void* ptr:动态开辟空间的首地址
注意:释放的空间一定是动态开辟的(就是在堆上开辟的),不然free是不起作用的。
free的使用:
#include<stdio.h> #include<stdlib.h> int main() {int* p=(int *)malloc(20);//开辟了20个字节的空间free(p);//将20个字节的空间还给了系统p=NULL;//如果不把p置为空指针,那么p就是野指针return 0; }
🐰动态开辟常见的错误
可能开辟空间失败,然后再去解引用会发生错误,所以malloc的返回值要去判断和越界访问。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> int main() {int* p=(int*)malloc(20);//可能开辟空间失败,然后再去解引用会发生错误,所以malloc的返回值要去判断//所以我们需要判断if(p==NULL){printf("%s",strerror(errno));//打印发生的错误return; }for(int i=0;i<5;i++){p[i]=i;}//越界访问for(int i=0;i<10;i++)//只开辟了5个int类型的空间,却访问了10个int类型的空间{p[i]=i;}free(p);p=NULL;return 0; }
对非动态开辟的空间进行释放
#include<stdio.h> #include<stdlib.h> int main() {int arr[10]={1,2,3};int *p=arr;free(p);//对非动态开辟的空间进行释放return 0; }
释放一部分动态开辟的空间
#include<stdio.h> #include<stdlib.h> int main() {int* p=(int*)malloc(40);for(int i=0;i<10;i++){p[i]=i;}p++;//p指向的就不是动态开辟空间的首地址free(p);//使用free释放一块动态开辟内存的一部分,不是从开辟空间的首地址开始释放的p=NULL;return 0; }
对一块空间多次释放
#include<stdio.h> #include<stdlib.h> int main() {int* p=(int*)malloc(40);free(p);//p=NULL;//如果释放了指针之后,再次释放是不会出错的,因为指针为空时,free不会做出任何反应free(p);//重复释放p=NULL;return 0; }
不能对空指针进行解引用操作
#include<stdio.h> #include<string.h> #include<stdlib.h> void GetMemory(char* str) {str=(char *)malloc(20);//str是p的临时拷贝,malloc动态开辟的空间,将首地址给了str,p仍然是空指针 } int main() {char* p=NULL;GetMemory(p);strcpy(p,"hello world");//这里对空指针进行了解引用操作printf("%s",p);return 0; }
野指针问题
#include<stdio.h> #include<string.h> #include<stdlib.h> char* GetMemory(void) {char str[]="hello world";//返回栈区空间的问题//GetMemory函数内部创建的数组str,str是临时创建,虽然返回了str数组的首地址,但是离开GetMemory函数之后,str内存会归还给系统,p的值虽然还是str数组的首地址,但是str空间已经归还给系统,str再去访问就是非法访问了。(栈区开辟的空间,离开作用域,栈区开辟的空间会被销毁)return str; } int main() {char* p=NULL;p=GetMemory();printf("%s",p);return 0; }
注:一定要记住
栈区:局部变量,函数形参
堆区:动态管理的空间(malloc,realloc,calloc,free)
静态区:静态变量,全局变量
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸
相关文章:

动态内存的开辟
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C 🔥座右铭:“不要等到什么都没有了,才下…...

【蓝桥杯-筑基篇】搜索
🍓系列专栏:蓝桥杯 🍉个人主页:个人主页 目录 递归树 1.递归构建二进制串 2.全排列的 DFS 解法 3.全排列的 BFS 解法 4.数的划分法 5.图书推荐 递归树 递归树是一种用于分析递归算法时间复杂度的工具。它可以将递归算法的执行过程可视化…...

week5-质数-最大公约数-快速幂-组合计数-博弈论
蓝桥 等差数列——欧几里得算法质数质数的判定——试除法分解质因数——试除法筛质数——埃氏筛法筛质数——线性筛法质数问题质数距离约数试除法求约数约数个数约数之和最大公约数-欧几里得算法(辗转相除法)扩展欧几里得算法裴蜀定理应用——线性同余方程消灭老鼠Hankson的趣…...

CloudCompare 二次开发(6)——插件中拖拽添加Qt窗口(区域生长算法为例)
目录 一、概述二、插件制作三、Cmake编译四、插件代码五、结果展示一、概述 手动拖拽的方式搭建Qt对话框界面的制作流程,以PCL中的点云区域生长算法为例进行制作。 二、插件制作 1、将....\plugins\example路径下的ExamplePlugin复制一份并修改名字为CCPointCloudProcess。 …...

2023值得推荐的高颜值Vue3.0 Web PC端UI框架,赶紧收藏学习!
Hello,我是前端胡说,本期给大家带来2023值得推荐的Vue3.0 UI组件库,希望大家喜欢! Vue3 正式发布已经有一段时间了,2022年2月也正式变成 Vue 项目的默认版本。在过去一年多的时间里,各大组件库、框架也紧跟…...

Springboot项目Aop、拦截器、过滤器横向对比
前言伟人曾经说过,没有调查就没有发言权(好像是伟人说的,不管谁说的,这句话是正确的),有些东西看着简单,张口就来,但很有可能是错的。我个人的经验是,aop、过滤器、拦截器的实现方式很简单&…...

为了之后找工作不被虐,每天刷3道《剑指offer》Day-1
本文已收录于专栏🌻《刷题笔记》文章目录前言💖 1、二维数组中的查找题目描述思路💖 2、替换空格题目描述思路💖 3、从尾到头打印链表题目描述思路一(反转函数)思路二(递归)思路二&a…...

Linux-磁盘管理介绍
Linux-磁盘管理介绍 计算硬盘介绍 硬盘是计算机主要存储媒介之一,由一个或者多个铝制或者玻璃制的碟片组成,碟片外覆盖有铁磁性材料,硬盘内部由磁道、柱面、扇区、磁头等部件组成; cylinder:柱面sector:扇区 磁道与…...

爬虫架构(一):爬虫中的去重处理
目录一、概要二、去重应用场景以及基本原理2.1 爬虫中什么业务需要使用去重2.2 去重实现的基本原理2.3 根据原始数据进行去重判断2.4 根据原始数据的特征值进行去重判断2.5 临时去重容器与持久化去重容器2.6 常用几种特殊的原始数据特征值计算三、基于信息摘要算法的去重3.1 信…...

算法刷题总结 (二) 回溯与深广搜算法
算法总结2 回溯与深广搜算法一、理解回溯算法1.1、回溯的概念1.2、回溯法的效率1.3、回溯法问题分类1.4、回溯法的做题步骤二、经典问题2.1、组合问题2.1.1、77. 组合 - 值不重复2.1.2、216.组合总和III - 值不重复且等于目标值2.1.3、17. 电话号码的字母组合 - 双层回溯2.1.4、…...

Linux 总结9个最危险的命令,一定要牢记在心!
rm -rf 命令 该命令可能导致不可恢复的系统崩坏。 rm -rf / #强制删除根目录下所有东西。 rm -rf * #强制删除当前目录的所有文件。 rm -rf . #强制删除当前文件夹及其子文件夹。 执行rm -rf 一定要想半天,搞明白自己在干什么. fork 炸弹 😦) { 😐:&am…...

spring cloud
spring cloud 分享 springboot:可以说是spring cloud的基础,是springMVC框架的简化,约定大于配置(在使用上、非功能上的简化) 可以说每个MPO Digital api就是springboot project(springboot项目) spring cloud…...

【9】核心易中期刊推荐——图像视觉与图形可视化
🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…...

0108Bean销毁-Bean生命周期详解-spring
Bean使用阶段,调用getBean()得到bean之后,根据需要,自行使用。 1 销毁Bean的几种方式 调用org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#destroyBean调用org.springframework.beans.factory.config.Conf…...

微信小程序可以进行dom操作吗?
小程序不能使用各种浏览器暴露出来的 DOM API,进行 DOM 选中和操作 原因:在小程序中,渲染层和逻辑层是分开的,分别运行在不同的线程中,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺…...

昇腾AI深耕沽上:港口辐射力之后,天津再添基础创新辐射力
作者 | 曾响铃 文 | 响铃说 AI计算正在以新基建联动产业集群的方式,加速落地。 不久前,天津市人工智能计算中心正式揭牌,该中心整体规划300P算力,2022年底首批100P算力上线投入运营,并实现上线即满载。 这是昇腾AI…...

基于YOLOv5的疲劳驾驶检测系统(Python+清新界面+数据集)
摘要:基于YOLOv5的疲劳驾驶检测系统使用深度学习技术检测常见驾驶图片、视频和实时视频中的疲劳行为,识别其闭眼、打哈欠等结果并记录和保存,以防止交通事故发生。本文详细介绍疲劳驾驶检测系统实现原理的同时,给出Python的实现代…...

【Linux】-- 进程优先级和环境变量
目录 进程的优先级 基本概念 如何查看优先级 PRI与NI NI值的设置范围 NI值如何修改 修改方式一 : 通过top指令修改优先级 修改方式二 : 通过renice指令修改优先级 进程的四个重要概念 环境变量 基本概念 常见的环境变量 查看环境变量 三种…...

iOS 紧急通知
一般通知 关于通知的各种配置和开发,可以参考推送通知教程:入门 – Kodeco,具有详细步骤。 紧急通知表现 紧急通知不受免打扰模式和静音模式约束。当紧急通知到达时,会有短暂提示音量和抖动(约2s)。未锁…...

即时零售:不可逆的进化
“人们经常问我,这个世界还是平的吗?我经常跟他们说,亲爱的,它真的是平的,比以前更平了。”2021年3月,《世界是平的》作者托马斯弗里德曼在演讲时说。如他所说,尽管逆全球化趋势加剧,…...

零售数据总结经验:找好关键分析指标和维度
各位数据的朋友,大家好,我是老周道数据,和你一起,用常人思维数据分析,通过数据讲故事。 每逢月末、季末、年终,运营部门的同事又要开始进行年终总结分析。那么,对零售连锁企业来说,…...

从零开始搭建游戏服务器 第一节 创建一个简单的服务器架构
目录引言技术选型正文创建基础架构IDEA创建项目添加Netty监听端口编写客户端进行测试总结引言 由于现在java web太卷了,所以各位同行可以考虑换一个赛道,做游戏还是很开心的。 本篇教程给新人用于学习游戏服务器的基本知识,给新人们一些学习…...

C++中那些你不知道的未定义行为
引子 开篇我们先看一个非常有趣的引子: // test.cpp int f(long *a, int *b) {*b 5;*a 1;return *b; }int main() {int x 10;int *p &x;auto q (long *)&x;auto ret f(q, p);std::cout << x << std::endl;std::cout << ret <&…...

java基础面试题(四)
Mysql索引的基本原理 索引是用来快速寻找特定的记录;把无序的数据变成有序的查询把创建索引的列数据进行排序对排序结果生成倒排表在倒排表的内容上拼接上地址链在查询时,先拿到倒排表内容,再取出地址链,最后拿到数据聚簇索引和非…...

@PropertySource使用场景
文章目录一、简单介绍二、注解说明1. 注解源码① PropertySource注解② PropertySources注解2. 注解使用场景3. 使用案例(1)新增test.properties文件(2)新增PropertySourceConfig类(3)新增PropertySourceTe…...

【C语言进阶:刨根究底字符串函数】strtok strerror函数
本节重点内容: 深入理解strtok函数的使用深入理解strerror函数的使用⚡strtok Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part ofstr1sep参数是个字符串,定义了用作分隔符的字符集合。第一个参数指…...

西安石油大学C语言期末重点知识点总结
大一学生一周十万字爆肝版C语言总结笔记 是我自己在学习完C语言的一次总结,尽管会有许多的瑕疵和不足,但也是自己对C语言的一次思考和探索,也让我开始有了写作博客的习惯和学习思考总结,争取等我将来变得更强的时候再去给它优化出…...

读《Multi-level Wavelet-CNN for Image Restoration》
Multi-level Wavelet-CNN for Image Restoration:MWCNN摘要一. 介绍二.相关工作三.方法摘要 存在的问题: 在低级视觉任务中,对于感受野尺寸与效率之间的平衡是一个关键的问题;普通卷积网络通常以牺牲计算成本去扩大感受野&#…...

【Linux】安装DHCP服务器
1、先检测网络是否通 get dhcp.txt rpm -qa //查看软件包 rpm -qa |grep dhcp //确定是否安装 yum install dhcp //进行安装 安装完成后 查询 rpm -ql dhcp 进行配置 cd /etc/dhcp 查看是否有遗留dhcpd.conf.rpmsave 删除该文件 cp /usr/share/doc/dhcp-4.1.1/dhcpd.conf.sampl…...

功能测试转型测试开发年薪27W,又一名功能测试摆脱点点点,进了大厂
咱们直接开门见山,没错我的粉丝向我投来了喜报,从功能测试转型测试开发,进入大厂,摆脱最初级的点点点功能测试,拿到高薪,遗憾的是,这名粉丝因为个人原因没有经过指导就去面试了,否则…...