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

C语言高阶【2】--动态内存管理【2】--柔性数组(这是个全新的知识点,不想了解一下吗?)

本章概述

  • 柔性数组
  • 总结C/C++中程序内存划分
  • 彩蛋时刻!!!!

柔性数组

数组这个东西,我想大家应该都不陌生了吧。但是,柔性数组这个东西可能你是第一次听说。

  • 柔性数组概念:在C99之前是没这个东西的,在C99之后就有这个东西了在C99中规定,结构体中的最后一个成员是大小未知的数组,那么这个数组就叫做柔性数组。进行结构展示:
struct st_type
{int i;int a[0];      //柔性数组成员 ,0就代表没有元素
};
// 有些编译器还可以这样写
struct st_type
{int i;int a[];      //柔性数组成员 
};
  • 柔性数组的特点
    • 1 .结构体是有大小的,由于我们的柔性数组大小是未知的。所以,在柔性数组之前,必须至少有一个知道大小的成员
    • 2.我们计算含有柔性数组的结构体的大小时,所计算的大小不包含柔性数组,因为它大小未知。进行代码展示:
#define  _CRT_SECURE_NO_WARNINGS	1
#include <stdio.h>
#include <stdlib.h>
struct stu
{int i;int arr[];
};
int main()
{printf("%d\n",sizeof(struct stu));return 0;
}

结果运行图:在这里插入图片描述

  • 柔性数组的使用柔性数组的使用要和动态内存函数一起使用我们一般用malloc进行空间的开辟。我们为这个含有柔性数组的结构体,开辟空间的大小至少为其它成员的大小。 进行代码展示:
#define  _CRT_SECURE_NO_WARNINGS	1
#include <stdio.h>
#include <stdlib.h>
struct stu
{int i;int arr[];
};
int main()
{struct stu* p = (struct stu*)malloc(8*sizeof(int));    //前4个字节给inti,//后4个字节给int arr[]if (p == NULL)return 1;p->i = 100;printf("%d\n",p->i);int i = 0;for (i = 0; i < 4; i++){p->arr[i] = i;}for (i = 0; i < 4; i++){printf("%d ",p->arr[i]);}free(p);p = NULL;return 0;
}

结果运行图:在这里插入图片描述
我们还可以模拟柔性数组,达到同样的效果,进行代码展示:

#define  _CRT_SECURE_NO_WARNINGS	1
#include <stdio.h>
#include <stdlib.h>
struct stu
{int i;int*p;
};
int main()
{struct stu* pp = (struct stu*)malloc(sizeof(struct stu));pp->p = malloc(4*sizeof(int));int i = 0;for (i = 0; i < 4; i++){*((pp->p)+i) = i;}for (i = 0; i < 4; i++){printf("%d ", *((pp->p) + i));}free(pp->p);free(pp);pp->p = NULL;pp = NULL;return 0;
}

结果运行图:在这里插入图片描述
这个模拟的代码要注意我们最后释放两次空间,第一次是p的空间,第二次是pp的空间,一定要先释放p,再释放pp。因为p是在pp之后才创建的空间,pp是p的爸爸,你要是把pp释放了,p就没有了,就无法释放p的空间了。如图所示:在这里插入图片描述

  • 柔性数组的优点
    • 1.方便我们释放内存,我们直接开辟好空间后,就会返回这个空间的地址,我们释放空间的时候,就可以直接通过这个地址直接释放。但是,如果按照我们的模拟代码的话,就需要释放两次,而且还要考虑释放顺序,这就很不方便。
    • 2.能够提升一定的运行效率。我们直接用柔性数组开辟出来的空间是连续的。但是,我们模拟的代码开辟的空间,里面存在内存碎片。我们为结构体开辟了一块空间,里面还为int i 和int*p都各自开辟了一块空间,而在它们之间还有空白的(多余)内存空间没用到,就出现了内存碎片。如图所示:在这里插入图片描述
      我们在这个结构体里面创建的成员比较少,内存碎片显示的不是很明显。但是,当我们创建的较多时,内存碎片就会显示的比较明显。

总结C/C++中程序内存划分

关于内存的划分以及各个部分存储什么数据,我们都已经讲过了。今天就给大家展示一下它们的对应关系,如图:在这里插入图片描述
对于内核空间,是操作系统操作的,我们程序员是无法进行访问的。为什么栈区和堆区会有向下和向上的箭头呢?其实,栈区和堆区的空间大小是灵活调整的。栈区多一点,堆区就少一点。反过来,堆区多一点,栈区就少一点。无论怎么变化,栈区和堆区的总和不变。 咱们以前讲过,静态区里面存放的是全局变量和常量。其实,划分细点就是分为数据段和代码段。数据段存放的全局变量和静态数据(static修饰的数据),代码段存放的是常量和编译后可执行的二进制代码。

彩蛋时刻!!!!

PLAY歌曲:《Shots》在这里插入图片描述
每章一句一鸣从此始,相望青云端。感谢你能看到这里,点赞+关注+收藏+转发是对我最大的鼓励,咱们下期见!!!


http://www.mrgr.cn/news/42921.html

相关文章:

  • C++入门基础知识99——【关于C++ 成员运算符】
  • Pikachu-Unsafe Fileupload-服务端check
  • etcd 快速入门
  • 【有啥问啥】SE(Squeeze-and-Excitation)架构详解
  • CUDA与TensorRT学习六:模型部署-CNN、模型部署-YOLOv8检测器、部署BEVFusion模型
  • vue-scrollto实现页面组件锚点定位
  • 最新版的dubbo服务调用(用nacos做注册中心用)
  • 【pytorch】张量求导
  • 华为杯”第十二届中国研究生数学建模竞赛-D题:单/多列车优化决策问题的研究(续)
  • 第一百零五周周报
  • 帝国CMS迁移网站后出现Create path fail: (建立目录不成功!请检查目录权限 )的解决办法
  • 中断-NVIC与EXTI外设详解(超全面)
  • 用 Delphi 做了一个简单的 CMS
  • 深度学习:基于MindSpore实现CycleGAN壁画修复
  • 认知杂谈98《抵御噪声干扰》
  • Robot Operating System——占据栅格地图(occupancy grid map)
  • valgrind 单例模式的自动释放(多线程)
  • 《计算机原理与系统结构》学习系列——计算机的算数运算(下)
  • SynchronousQueue 的 常用场景及使用示例
  • 【AUTOSAR 基础软件】COM模块详解(通信)