第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,一经查实,立即删除!

相关文章

python将.db数据库文件转成Excel文档

python实现.db数据库转Excel 程序实现 上一篇文章程序实现以下功能&#xff1a; 1.读取一个Excel文件,文件名通过函数传参数传入 2.将文件读取的内容保存到一个数据库文件中 3.数据库的文件名以传入的Excel文件的文件名命名 4.将excel文件的工作簿的名字作为数据库的表单名 5…

apache_exporter安装说明

Apache Exporter 问题描述 需要监控apache服务&#xff0c;部署了apache_exporter&#xff0c;对过程进行一下记录。 源码参见apache_exporter ①下载 https://github.com/Lusitaniae/apache_exporter/releases②解压缩 tar -xzvf apache_exporter-0.7.0.linux-amd64.tar…

深入了解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;是项目中非常重要的一部…

JUnit 5 注解总结与解析

前言 大家好&#xff0c;我是chowley&#xff0c;通过前篇的JUnit实践&#xff0c;我对这个框架产生了好奇&#xff0c;除了断言判断&#xff0c;它还有哪些用处呢&#xff1f;下面来总结一下它的常见注解及作用。 正文 在Java单元测试中&#xff0c;JUnit是一种常用的测试框…

linux互斥锁:递归锁,非递归锁用法详解

在实际的项目中经常涉及到共享资源&#xff0c;共享资源被多个线程访问会出现竞争现象&#xff1b;为了解决竞争和保护共享资源常用的机制之一就是互斥锁&#xff01; 互斥锁又分为递归锁和非递归锁&#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;更多干货持…

QT styleSheet——控件设置样式表

QT开发中&#xff0c;需要设置多种多样的控件表现形式&#xff0c;QT实现的styleSheet能够满足多种多样的场景&#xff0c;这里简单的记录下一些我常用的 设置透明背景&#xff0c;鼠标悬浮时&#xff0c;设置背景色&#xff1a; pushButton->setStyleSheet("QPushBu…

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…

每周编辑精选|希尔贝壳语音数据集系列上线、中国学者建立乳腺癌预后评分系统 MIRS

&#x1f3ee;新春佳节&#xff0c;归程千里为团圆 &#x1f3ee;人间烟火&#xff0c;年味浓浓阖家欢 辞别玉兔&#xff0c;金龙迎春。明晚就是大年三十除夕夜了&#xff01;HyperAI超神经在这里提前祝大家新春快乐&#xff5e;龙行龘龘(d)&#xff01;本周 hyper.ai 官网上线…

Lua协程-coroutine

lua也有协程这个机制&#xff0c;用以完成非抢占式的多任务处理。 协程与线程 协程和线程类似&#xff0c;有自己的堆栈、局部变量、指令指针等等。但同时也有不一致的地方&#xff0c;其中最重要的地方在于多线程程序可以同一时间运行多个线程&#xff0c;而协程同一时间只能…

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…

【leetcode热题100】删除排序链表中的重复元素

难度&#xff1a; 简单通过率&#xff1a; 41.5%题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目描述 给定一个排序链表&#xff0c;删除所有重复的元素&#xff0c;使得每个元素只出现一次。 示例 1: 输入: 1->1->…