当前位置: 首页 > news >正文

C语言动态内存管理(三)

目录

  • 五、C/C++程序的内存开辟
    • 1.图解
    • 2.关键点
  • 六、柔性数组
    • 1.什么是柔性数组
    • 2.两种语法形式
    • 3.柔性数组的特点
    • 4.柔性数组的创建及使用
      • 在这个方案中柔性数组的柔性怎么体现出来的?
    • 5.不用柔性数组,实现数组可大可小的思路
    • 6.对比
  • 总结

五、C/C++程序的内存开辟

1.图解

在这里插入图片描述
(1)内核空间:留给操作系统内核用,用户不能使用,自己写的程序没有权限访问内核空间
(2)栈区:存放局部变量
(3)内存映射段:(在Linux专栏中介绍)
(4)堆区:malloc,calloc,realloc动态开辟的空间

✨关于realloc在C语言动态内存管理(一)中讲了调整动态内存空间的作用,这里补充realloc函数的第一个参数是空指针NULL的时候,作用相当于开辟内存空间
举例:
realloc(NULL,20);
这句代码相当于malloc(20);

(5)数据段:存放全局变量,静态变量(静态变量不管是全局的还是局部的都放在数据段中)
(6)代码段:自己写的代码编译之后的汇编指令或者二进制指令

2.关键点

(1)栈区:
I.函数内的局部变量进作用域创建,出作用域销毁
II.向栈区申请的空间是有限的,不断地向栈区申请空间,就会出现栈溢出现象
III.栈区主要存放运行函数而分配的局部变量,函数参数,返回数据,返回地址等。
(2)堆区
一般由程序员分配释放。若程序员不释放,程序结束时可能由操作系统回收。分配方式类似于链表。
(3)数据段(静态区)
存放全局变量,静态数据。程序结束后由系统释放
(4)代码段
存放函数体(类成员函数和全局函数)的二进制代码

六、柔性数组

1.什么是柔性数组

在C99语法中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员。

2.两种语法形式

✨第一种:结构体中最后一个数组的大小指定为0

struct S {int n;int a[0];//柔性数组成员
};

✨第二种:结构体中的最后一个数组未指定大小

struct S {int n;int a[];//柔性数组成员
};

3.柔性数组的特点

(1)结构中的柔性数组成员前面必须至少有一个其他成员
(2)sizeof返回的这种结构大小不包含柔性数组的内存

也就是说包含柔性数组成员的结构体在用sizeof算这个结构体大小时,不计入柔性数组的大小

(3)包含柔性数组成员的结构用malloc函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小
✨注意:
包含柔性数组成员的结构体创建时与一般结构体创建的方法不同。不能直接创建写成struct S ss;

4.柔性数组的创建及使用

柔性数组方案一

//柔性数组方案一
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>struct S {int n;char c;int arr[0];//柔性数组成员
};
int main() {struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));/*(1)内存中放的是struct S类型的数据,开辟空间的地址应该是struct S*(2)结构体大小:包含除柔性数组成员的其他成员(3)10*sizeof(int)是柔性数组里打算放的东西,为柔性数组留了10个整型*///判断是否开辟成功if (ps == NULL) {printf("%s\n",strerror(errno));return 1;}//使用ps->n = 55;ps->c = 'y';int i = 0;for (i = 0; i < 10; i++) {ps->arr[i] = i;}for(i = 0; i < 10; i++) {printf("%d\n", ps->arr[i]);}//调整arr数组的大小struct S* ptr = (struct S*)malloc(sizeof(struct S) + 20 * sizeof(int));if (ptr == NULL) {printf("%s\n", strerror(errno));return 1;}else {ps = ptr;//开辟成功的话最好用原来维护开辟好的空间的ps指针来维护这块空间}//使用//...//释放free(ps);ps = NULL;return 0;
}

在这里插入图片描述
在这里插入图片描述

在这个方案中柔性数组的柔性怎么体现出来的?

✨如果将结构体中arr长度写做10,结构体类型一旦创建好了,数组大小就不能改变了。不能每次使用的时候才进行更改数组的长度,因为一旦编译,结构体中的数组大小就固定了。
✨而柔性数组成员的空间是malloc出来的,malloc的空间可用realloc调整,那么这个数组的大小就柔性可变了。

5.不用柔性数组,实现数组可大可小的思路

结构中指针方案二

#include<stdio.h>
#include<stdlib.h>
struct S {int n;char c;int* arr;
};
int main() {struct S* ps = (struct S*)malloc(sizeof(struct S));if (ps == NULL) {perror("malloc");return 1;}int* ptr = (int*)malloc(10 * sizeof(int));if (ptr == NULL) {perror("malloc");return 1;}else {ps->arr = ptr;//开辟成功,把地址交给arr,arr指向这块空间/*arr指向这块空间,那么arr就可以像数组一样访问这块空间这块空间是malloc来的,所以不够时就可以用realloc进行扩容*/}//使用ps->n = 100;ps->c = 'y';int i = 0;for (i = 0; i < 10; i++) {ps->arr[i] = i;/*因为arr里面放的是这块空间的起始地址,和数组名一样把这块空间想象成连续的数组,数组名表示首元素的地址*/}//打印for (i = 0; i < 10; i++) {printf("%d ", ps->arr[i]);}//扩容-->调整arr数组的大小ptr = realloc(ps->arr, 20 * sizeof(int));if (ptr == NULL) {perror("realloc");return 1;}else {ps->arr = ptr;}//使用//...//释放//注意:释放动态内存开辟空间的顺序:后开辟的先释放free(ps->arr);ps->arr = NULL;free(ps);ps = NULL;return 0;
}

在这里插入图片描述
在这里插入图片描述

6.对比

柔性数组方案一
(1)malloc一次free一次
容易维护空间,不易出错
(2)malloc次数少,内存碎片较少,内存的使用率就会高一些
(3)有利于访问速度

柔性数组在内存空间中是连续的
涉及到局部性原理
如果内存是连续的,拿数据进行内存访问时,不是直接去拿,而是把内存中数据加载到寄存器里面。如果使用某个位置的数据,寄存器后面有空的话就会紧接着把它后面的数据加载到寄存器中。如果使用后面数据的话,在寄存器中已经拿到了,这样的效率更高。
在结构中指针方案二:
开辟了两块不连续的空间,在访问其中一块空间的时候,不断加载的事该空间后面的数据到寄存器,并没有把另一块空间的数据加载。访问另一块空间的数据时,寄存器中没有找到,跑到内存中去找,此时整体的效率就下降了。

总结

关于动态内存管理的全部知识就分享到这里啦,哪里有问题的话,欢迎各位朋友在评论区留言,可以点赞收藏博客关注后续的内容哦👻👻

相关文章:

C语言动态内存管理(三)

目录 五、C/C程序的内存开辟1.图解2.关键点 六、柔性数组1.什么是柔性数组2.两种语法形式3.柔性数组的特点4.柔性数组的创建及使用在这个方案中柔性数组的柔性怎么体现出来的? 5.不用柔性数组&#xff0c;实现数组可大可小的思路6.对比 总结 五、C/C程序的内存开辟 1.图解 &a…...

通过cmake工程生成visual studio解决方案

1、前言 visual studio是一个很强大的开发工具&#xff0c;这个工具主要是通过解决方案对我们的源码进行编译等操作。但是我们很多时候拿到的可能并不是一个直接的解决方案&#xff0c;可能是是一个cmake工程&#xff0c;那么这个时候我们就需要通过cmake工程生成解决方案&…...

STM32CubeMX配置STM32G031多通道ADC + DMA采集(HAL库开发)

时钟配置HSI主频配置64M 勾选打开8个通道的ADC 使能连续转换模式 添加DMA DMA模式选择循环模式 使能DMA连续请求 采样时间配置160.5 转换次数为8 配置好8次转换的顺序 配置好串口&#xff0c;选择异步模式配置好需要的开发环境并获取代码 修改main.c 串口重定向 #include &…...

Vue入门项目——WebApi

Vue入门——WebApi vue3项目搭建组合式API响应式APIreactive()ref() 生命周期钩子computed计算属性函数watch监听函数父子通信模板引用组合选项 vue3项目搭建 简单看下Vue3的优势吧 下载安装npm及node.js16.0以上版本&#xff08;确保安装成功可用如下代码检查版本&#xff0…...

【电源专题】电量计参数RSOC/RM/FCC定义

在文章【电源芯片】电量计(Gauge)介绍中我们讲到电量计的功能就是监测电池、计量电量。 那么电量计其实也是有很多算法的,比如【电源专题】电量计估计电池荷电状态方法(开路电压法及库仑计法)的差别文章所说的开路电压法和库仑计法。当然还有如阻抗跟踪法、CEDV算法等。 …...

实际开发中,React应用常见问题【持续更新中】

实际开发中&#xff0c;React应用常见问题【持续更新中】 实际开发中&#xff0c;React应用常见问题【持续更新中】 一、路由相关 “react-router-dom”: “^6.14.2”, “react”: “^18.2.0”, 1、监听路由 import { useLocation } from react-router-domexport default func…...

HTML5前端开发工程师的岗位职责说明(合集)

HTML5前端开发工程师的岗位职责说明1 职责 1、根据产品设计文档和视觉文件&#xff0c;利用HTML5相关技术开发移动平台的web前端页面; 2、基于HTML5.0标准进行页面制作&#xff0c;编写可复用的用户界面组件; 3、持续的优化前端体验和页面响应速度&#xff0c;并保证兼容性和…...

Go编写服务监管程序

前言 程序的目的&#xff1a;一个基于Linux系统下的进程监控与管理工具&#xff0c;它能够监控指定的进程或服务的运行情况&#xff0c;并在发现它们不存在或出现异常时自动进行重启操作。这个程序就像一个可靠的看门狗&#xff0c;时刻守护着系统的稳定运行。 程序的本身是周期…...

API商品详情:详尽呈现产品信息的利器

API商品详情&#xff1a;详尽呈现产品信息的利器 随着电子商务的迅速发展&#xff0c;越来越多的企业和开发者开始关注和利用API来实现灵活、高效的商品展示和推广。而在这一领域中&#xff0c;API商品详情成为了无可替代的利器&#xff0c;为用户提供了极为详尽的产品信息。 …...

Cisco 路由器配置管理

大多数网络中断的最常见原因是错误的配置更改。对网络设备配置的每一次更改都伴随着造成网络中断、安全问题甚至性能下降的风险。计划外更改使网络容易受到意外中断的影响。 Network Configuration Manager 网络更改和配置管理 &#xff08;NCCM&#xff09;解决方案&#xff…...

java面试真题附参考答案【下册】

tips&#xff1a;下面简述题为java面试真题&#xff0c;阅读本文且感兴趣的&#xff0c;还有将要面试的小伙伴有条件的准备一下笔和纸&#xff0c;将之转述出来成为自己的知识&#xff0c;希望接下来的面试好运连连 上一册&#xff1a;java面试真题【上册】_CsDn.FF的博客-CSD…...

2023牛客多校第三场 B.Auspiciousness

传送门 前题提要:没得说,赛时根本没想到dp,赛后翻各大题解看了很久,终于懂了dp的做法,故准备写一篇题解. 首先,先定义一下我们的 d p dp dp方程,考虑将处于 [ 1 , n ] [1,n] [1,n]的数当做小数,将处于 [ n 1 , 2 ∗ n ] [n1,2*n] [n1,2∗n]的数当做大数.那么对于我们的摸牌结…...

Numpy—数组的分隔与转置

⛳数组的切分 split 分隔 numpy.split 函数沿特定 的轴将数组分割为子数组&#xff0c;格式如下&#xff1a; numpy.split(ary, indices_or_sections, axis)参数说明&#xff1a; arry&#xff1a;被分割的数组。indices_or_sections&#xff1a;如果是一个整数&#xff0c;就…...

PyTorch中级教程:深入理解自动求导和优化

在你已经掌握了如何使用PyTorch构建神经网络的基础上&#xff0c;接下来我们将深入探讨PyTorch的两个核心特性&#xff1a;自动求导&#xff08;Autograd&#xff09;和优化&#xff08;Optimization&#xff09;。这两个特性在深度学习模型的训练过程中起着至关重要的作用。 …...

ES6基础知识六:你是怎么理解ES6中 Promise的?使用场景?

一、介绍 Promise&#xff0c;译为承诺&#xff0c;是异步编程的一种解决方案&#xff0c;比传统的解决方案&#xff08;回调函数&#xff09;更加合理和更加强大 在以往我们如果处理多层异步操作&#xff0c;我们往往会像下面那样编写我们的代码 doSomething(function(resu…...

数据库CAST()函数,格式(CAST AS decimal)

语法&#xff1a; CAST (expression AS data_type) 参数说明&#xff1a; expression&#xff1a;任何有效的SQServer表达式。 AS&#xff1a;用于分隔两个参数&#xff0c;在AS之前的是要处理的数据&#xff0c;在AS之后是要转换的数据类型。 data_type&#xff1a;目标系统…...

LRU 缓存结构

文章目录 LRU实现 LRU 优先去除最久没有访问到的数据。 实现 通过组合哈希表&#xff08;Hash Table&#xff09;和双向链表&#xff08;Doubly Linked List&#xff09;实现 LRU 缓存。并且以 O(1) 的时间复杂度执行 get 和 put 操作核心是对节点的新增、访问都会让节点移动…...

DAY1,Qt [ 手动实现登录框(信息调试类,按钮类,行编辑器类,标签类的使用)]

1.手动实现登录框&#xff1b; ---mychat.h---头文件 #ifndef MYCHAT_H #define MYCHAT_H#include <QWidget> #include <QDebug> //打印信息 #include <QIcon> //图标 #include <QPushButton> //按钮 #include <QLineEdit> //行编辑器类 #in…...

25.8 matlab里面的10中优化方法介绍—— 拉各朗日乘子法求最优化解(matlab程序)

1.简述 拉格朗日乘子法&#xff1a; 拉格朗日乘子法&#xff08;Lagrange multipliers&#xff09;是一种寻找多元函数在一组约束下的极值的方法。通过引入拉格朗日乘子&#xff0c;可将有 变量与 约束条件的最优化问题转化为具有变量的无约束优化问题求解 举个例子&#xff…...

2023年自然语言处理与信息检索国际会议(ECNLPIR 2023) | EI Compendex, Scopus双检索

会议简介 Brief Introduction 2023年自然语言处理与信息检索国际会议(ECNLPIR 2023) 会议时间&#xff1a;2023年9月22日-24日 召开地点&#xff1a;中国杭州 大会官网&#xff1a;ECNLPIR 2023-2023 Eurasian Conference on Natural Language Processing and Information Retr…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...