第21讲:动态内存管理

1.为什么要有动态内存分配

2.malloc和free

3.calloc

4.realloc

5.笔试题

6.总结c/c++中程序内存区域划分

1.为什么要有动态内存分配

为了调整申请的空间大小,使程序员可以申请和释放空间,提高程序的灵活性

2.malloc和free

作用:分配一块连续可用的空间

头文件:stdlib.h

参数:类型是size_t,size是预分配大小(单位是字节)

返回值:类型是void*,若开辟失败,返回NULL;若开辟成功,返回这块空间(malloc开辟的空间)的首指针。

用法:开辟空间后,我们要保留这块空间的首指针,但malloc的返回值类型是void*,保留时要注意强制类型转换。最后,当开辟的空间不再用时,要用free函数释放空间,否则该空间将被一直占用,直到程序结束时才会被操作系统收回。

作用:释放动态开辟的内存。

头文件:stdlib.h

参数:类型是void*,参数是需解除分配的内存块;参数可以是NULL,此时函数什么也不做

返回值:无

上述代码看似没有问题,但却有个大问题。

如果malloc开辟空间失败呢?

返回NULL,而且我们还对NULL解引用了,这是非常可怕的,所以,修改如下:

这样才合适。

还有一个问题,释放pa指向的空间后,pa和p就是野指针了,要置NULL才合适

3.calloc

作用:开辟num个size字节的空间,并将每个开辟的字节初始化为0

头文件:stdlib.h

参数:类型都是size_t,num是开辟的元素个数,size是为每个元素分配的大小

返回值:和malloc一致

特点:与malloc区别不大,但malloc是不会对开辟空间初始化的,但calloc会。

4.realloc

作用:调整动态开辟的空间大小

头文件:stdlib.h

参数1:类型是void*,参数1是需调整的动态开辟的空间

参数2:类型是size_t,参数2是调整后的空间大小

参数1可以是NULL,此时将开辟一块size字节的空间,并返回首指针

返回值:类型是void*,若开辟失败,返回NULL;若开辟成功,返回调整后空间的首指针

注意:开辟后的空间未必是在原来的位置!所以要保留realloc的返回值才比较合适

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
int main()
{int* p = (int*)malloc(16);//开辟空间,保留首指针if (p == NULL){exit(-1);}int* pa = p;p = (int*)realloc(pa, 32);if (p == NULL){exit(-1);}pa = p;free(pa);//回收空间pa = NULL;//防野指针p = NULL;return 0;
}

5.笔试题

题目1

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void getmemory(char* p)
{p = (char*)malloc(100);
}
void test()
{char* str = NULL;getmemory(str);strcpy(str, "helo world");printf(str);
}
int main()
{test();return 0;
}

其实吧,并不会打印hello world,str是空指针,将指针变量传给getmemory不会改变指针变量,形参只是实参的一份临时拷贝,改变形参不会改变实参。

应将指针变量的地址传上去,然后解引用才能改变指针变量str

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void getmemory(char** p)
{*p = (char*)malloc(100);
}
void test()
{char* str = NULL;getmemory(&str);strcpy(str, "helo world");printf(str);
}
int main()
{test();return 0;
}

这样就没问题了

题目2

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* getmemory()
{char p[] = "hello world";return p;
}
void test()
{char* str = NULL;str = getmemory();printf(str);
}
int main()
{test();return 0;
}

看起来没什么问题,因为字符串常量是存储在代码段的,不是栈区,即使出了函数也不会销毁,char p【】等价于char* p, 而p是指向字符串常量的指针,出函数后,p就被销毁了,但是变量p里面装的指针(也就是字符串常量的首指针)被返回了,应该是可以打印的。

但是吧,有个误区(上面红字是错的),我们忽略了字符数组初始化的特殊性,本代码的实质是将字符串拷贝一份,放到字符数组中,而这个字符数组是在栈区的,p是字符数组的首指针。出了函数,p指向的空间就被回收了,所以不能打印。

但是,我们只要稍稍修改:

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* getmemory()
{const char* p = "hello world";return (char*)p;
}
void test()
{char* str = NULL;str = getmemory();printf(str);
}
int main()
{test();return 0;
}

这个代码是可以打印的,因为p不再是数组名了,字符数组的特殊初始化没有了,p就是字符串常量的首指针!

题目3

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void getmemory(char** p,int num)
{*p = (char*)malloc(num);
}
void test()
{char* str = NULL;getmemory(&str, 100);strcpy(str, "hello");printf(str);
}
int main()
{test();return 0;
}

这个呀,没什么问题,是对的。因为我们取出str的地址,可以通过解引用的方式改变str。另外,在函数里用malloc申请内存,也是在堆区申请,函数结束对堆区的空间不影响。

6.总结c/c++中程序内存区域划分

堆区:动态开辟内存是在堆区上开辟的

栈区:声明变量,调用函数是在栈区申请内存

代码段:可执行代码,只读常量(例如字符串常量)

数据段(静态区):全局变量,静态变量储存在静态区

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/674044.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入了解Redis:选择适用于你的场景的持久化方案

自然语言处理的发展 文章目录 自然语言处理的发展强烈推荐前言&#xff1a;Redis提供了几种主要的持久化方案&#xff1a;RDB快照持久化&#xff1a;工作原理&#xff1a; AOF日志文件持久化&#xff1a;混合持久化&#xff1a; 总结强烈推荐专栏集锦写在最后 强烈推荐 前些天…

相机图像质量研究(7)常见问题总结:光学结构对成像的影响--镜片固化

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

戴上HAUWEI WATCH GT 4,解锁龙年新玩法

春节将至&#xff0c;华为WATCH GT 4作为一款颜值和实力并存的手表&#xff0c;能为节日增添了不少趣味和便利。无论你是钟情于龙年表盘或定制属于自己的表盘&#xff0c;还是过年用来抢红包或远程操控手机拍全家福等等&#xff0c;它都能成为你的“玩伴”。接下来&#xff0c;…

C语言 服务器编程-日志系统

日志系统的实现 引言最简单的日志类 demo按天日志分类和超行日志分类日志信息分级同步和异步两种写入方式 引言 日志系统是通过文件来记录项目的 调试信息&#xff0c;运行状态&#xff0c;访问记录&#xff0c;产生的警告和错误的一个系统&#xff0c;是项目中非常重要的一部…

零基础学Python之整合MySQL

Python 标准数据库接口为 Python DB-API&#xff0c;Python DB-API为开发人员提供了数据库应用编程接口。 不同的数据库你需要下载不同的DB API模块&#xff0c;例如你需要访问Oracle数据库和Mysql数据&#xff0c;你需要下载Oracle和MySQL数据库模块。 DB-API 是一个规范. 它…

【51单片机】要实现动静态数码管,你首先需要知道这些【数码管项目前置知识】

前言 大家好吖&#xff0c;欢迎来到 YY 滴单片机系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 主要内容含&#xff1a; 本章节内容为【实现动静态数码管】项目的第一个模块完整章节&#xff1a;传送门 欢迎订阅 YY滴C专栏&#xff01;更多干货持…

Unity接入GVoice腾讯实时语音

Unity接入GVoice腾讯实时语音 一、介绍二、注册GVoice创建项目语音服务1.创建项目2.申请语音权限3.项目管理查看SDK初始化的一些参数和基本信息4.GVoice检测 三、SDK下载SDK是分为两种类型&#xff1a;独立版集成板 SDK放入Unity工程中 四、语音代码写法五、GVoice踩坑语音权限…

【canvas】获取鼠标点击位置坐标的颜色信息

在项目当中&#xff0c;要实现某业务需求例如PS魔棒功能时&#xff0c;则需要获取点击坐标的颜色信息。 功能不复杂&#xff0c;代码也很少&#xff0c;一看便知~~ 核心API为getImageData&#xff0c;传入4个参数&#xff0c;前2个为点击坐标xy&#xff0c;后2个都传1&#xf…

python调用golang中函数方法

一、原因说明&#xff1a;由于simhash方法有多种实现方式&#xff0c;现python中simhash方法与golang中的不一样&#xff0c;需要两者代码生成结果保持一致&#xff0c;故采用python中的代码调用golang编译的so文件来实现。 环境配置&#xff1a;①Windows10系统要有gcc环境&a…

ADSelfService Plus发布离线MFA功能,强化远程工作安全性

ManageEngine ADSelfService Plus推出离线多因素身份验证&#xff0c;提升远程工作安全性确保通过先进的验证方法对企业数据进行授权访问&#xff0c;无论时间、地点或连接问题如何允许远程用户安全进行身份验证&#xff0c;即使未连接到认证服务器或互联网使用高度安全的基于T…

Vue前端框架--Vue工程项目问题总结{脚手架 Vue-cli}

Vue脚手架部署问题总结 我所遇到的一共两大问题 只有先执行npm install之后 才能run serve 否则会报错 vue-cli-serve不是内部或者外部的命令&#xff0c;也不是可运行的程序或者批处理文件的错误 1. 运行npm install会报错 2. 运行npm run serve报错 nodejs官网为 https://no…

C#中实现串口通讯和网口通讯(使用SerialPort和Socket类)

仅作自己学习使用 1 准备部份 串口通讯需要两个调试软件commix和Virtual Serial Port Driver&#xff0c;分别用于监视串口和创造虚拟串口。网口通讯需要一个网口调试助手&#xff0c;网络上有很多资源&#xff0c;我在这里采用的是微软商店中的TCP/UDP网络调试助手&#xff0…

cleanmymacX和腾讯柠檬哪个好用

很多小伙伴在使用Mac时&#xff0c;会遇到硬盘空间不足的情况。遇到这种情况&#xff0c;我们能做的就是清理掉一些不需要的软件或者一些占用磁盘空间较大的文件来腾出空间。我们可以借助一些专门的清理工具&#xff0c;本文中我们来推荐几款好用的Mac知名的清理软件。并且将Cl…

SQL在云计算中的新角色:重新定义数据分析

文章目录 1. 云计算与数据分析的融合2. SQL在云计算中的新角色3. 分布式SQL查询引擎4. SQL-on-Hadoop解决方案5. SQL与其他数据分析工具的集成6. 实时数据分析与SQL7. SQL在云数据仓库中的角色8. 安全性与隐私保护9. SQL的未来展望《SQL数据分析实战&#xff08;第2版&#xff…

14.scala隐式转换

目录 概述实践代码执行结果 结束 概述 隐式转换&#xff1a;偷偷的(隐式)对现有功能进行增强(转换) 实践 代码 package com.fun.scalaimport java.io.File import scala.io.Sourceobject ImplicitApp {def main(args: Array[String]): Unit {// implicit 2 to 等价 &…

vuecli3 执行 npm run build 打包命令报错:TypeError: file.split is not a function

问题 今天有个项目在打包的时候遇到了一个问题&#xff0c;就是执行 npm run build 命令的时候报错了&#xff0c;如下&#xff1a; 解决 我排查了一下&#xff0c;模拟代码如下&#xff1a;在打包的时候用了 MinChunkSizePlugin const webpack require("webpack"…

LabVIEW多任务实时测控系统

LabVIEW多任务实时测控系统 面对现代化工业生产的复杂性和多变性&#xff0c;传统的测控系统已难以满足高效、精准、可靠的监控和控制需求。因此&#xff0c;开发一种基于LabVIEW的智能测控系统&#xff0c;能够提高生产效率&#xff0c;保证生产安全&#xff0c;是解决现代工…

怎么清理电脑内存?详细图文教程分享!

“我的电脑用了才不到一年&#xff0c;现在内存总是不足。想问问大家平常遇到电脑内存不足的情况时有什么好用的清理方法吗&#xff1f;” 随着电脑使用时间的增长&#xff0c;内存占用可能会不断增加&#xff0c;导致电脑运行缓慢。为了保持电脑的良好性能&#xff0c;定期清理…

手把手教你实现Kmeans聚类,不使用MATLAB工具箱,纯手写matlab代码免费获取,UCI数据集为例...

K均值&#xff08;K-means&#xff09;是一种常用的聚类算法&#xff0c;用于将数据集划分为K个不同的组&#xff08;簇&#xff09;&#xff0c;使得每个数据点属于与其最近的均值点所代表的簇。K均值算法的基本思想是通过迭代优化&#xff0c;将数据点分配到K个簇中&#xff…

【RT-DETR有效改进】重参数化模块DiverseBranchBlock助力特征提取(附代码 + 修改教程)

&#x1f451;欢迎大家订阅本专栏&#xff0c;一起学习RT-DETR&#x1f451; 一、本文介绍 本文给大家带来的是改进机制是一种替换多元分支模块&#xff08;Diverse Branch Block&#xff09;&#xff0c;Diverse Branch Block (DBB) 是一种用于增强卷积神经网络性能的结构…