C语言定长数组 变长数组 柔性数组

C语言定长数组 变长数组 柔性数组

文章目录

  • C语言定长数组 变长数组 柔性数组
    • 1. 定长数组
    • 2. 变长数组
    • 3. 柔性数组
      • 3.1 结构体的大小
      • 3.2 柔性数组的使用

1. 定长数组

在C99标准之前,C语言在创建数组的时候,数组的大小只能使用常量常量表达式来,或者在初始化数组时,省略数组的大小,这就是所谓的定长数组

#include <stdio.h>
int main()
{int arr1[10];int arr2[10 + 5];int arr3[] = {1,2,3,4,5,6,7,8,9,10};return 0;
}

2. 变长数组

有定长数组这样的语法限制,让我们创建数组不够灵活,有时数组大小给大了浪费空间,有时数组大小给小了不够用,所以在C99标准之后,有个一个变⻓数组(variable-length array,简称 VLA)的概念,允许我们在创建数组的时候使用变量

int n = a + b;
int arr[n];

在上述示例中,arr 就是变长数组,因为它的长度取决于变量n的值,编译器没法事先确定,只有运行时才能知道变量n是多少

变长数组特点:

  1. 变长数组⻓度只有运⾏时才能确定,所以变⻓数组不能初始化
  2. 变⻓数组的意思是数组的⼤⼩是可以使⽤变量来指定的,在程序运⾏的时候,根据变量的⼤⼩来指定数组的元素个数,⽽不是说数组的⼤⼩是可变的。数组的⼤⼩⼀旦确定就不能再变化了。

在VS2022中是不支持变长数组的,没法测试,在gcc编译器上可以测试

#include <stdio.h>
int main()
{int n = 0;scanf("%d", &n);//根据输⼊数值确定数组的⼤⼩int arr[n];int i = 0;for (i = 0; i < n; i++){scanf("%d", &arr[i]);}for (i = 0; i < n; i++){printf("%d ", arr[i]);}return 0;
}

在这里插入图片描述

3. 柔性数组

那么有没有一种数组,在确定确定数组的大小,还可以根据需要扩大数组
在C99 中,结构体中的最后⼀个元素允许是未知⼤⼩的数组,这就叫做『柔性数组』成员。
例如:

struct S
{int i;char c;int arr[];
};

在上述示例中,arr就是变长数组

变长数组的特点:

  1. 在结构体中
  2. 最后一个成员
  3. 未知大小的数组

这样的数组就是柔性数组

3.1 结构体的大小

struct S
{int i;char c;int arr[];
};#include <stdio.h>
int main()
{printf("%zd\n", sizeof(struct S));return 0;
}

代码运行结果:>8
根据结构体对齐规则,int 4个字节,char 1个字节,总共5个字节,不为最大对齐数4的倍数,对齐至8字节

在存在柔性数组的结构体中,计算结构体的大小时,不会计算柔性数组的大小

3.2 柔性数组的使用

柔性数组是通过 malloc realloc的方式来实现数组大小的扩大的

代码一:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>struct S
{int i;char c;int arr[];
};
int main()
{struct S* p = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int)); //通过结构体指针来访问结构体,开辟一个结构体大小 + 想要开辟数组大小的空间if (p == NULL)  //判断开辟是否成功{perror("malloc fail");return 1;}//使用柔性数组int i = 0;  for (i = 0; i < 10; i++) {p->arr[i] = i;}struct S* tmp = (struct S*)realloc(p, sizeof(struct S) + 15 * sizeof(int)); //调整数组大小if (tmp != NULL)  //判断是否调整成功{p = tmp;}else{perror("realoc fail");return 1;}//使用for (i = 10; i < 15; i++){p->arr[i] = i;}//打印for (i = 0; i < 15; i++){printf("%d ", p->arr[i]);}//释放free(p);p = NULL;return 0;
}

看不懂的可以去看看动态内存管理malloc calloc realloc free这篇博客

代码二:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>struct S
{int i;char c;int *arr;
};
int main()
{struct S* p = (struct S*)malloc(sizeof(struct S));  //开辟一块空间给结构体if (p == NULL)  //判断开辟是否成功{perror("malloc fail");return 1;}p->arr = (int*)malloc(10 * sizeof(int));  //开辟数组if (p->arr == NULL)  //判断开辟是否成功{perror("malloc fail");return 1;}//使用int i = 0;for (i = 0; i < 10; i++){p->arr[i] = i;}int* tmp = (int*)realloc(p->arr,15 * sizeof(int)); //调整结构体大小if (tmp != NULL) //判断{p->arr = tmp;}else{perror("realoc fail");return 1;}//使用for (i = 10; i < 15; i++){p->arr[i] = i;}//打印for (i = 0; i < 15; i++){printf("%d ", p->arr[i]);}//释放free(p->arr);p->arr = NULL;free(p);p = NULL;return 0;
}

代码一代码二可以使用了柔性数组,但是代码一有两个好处:

  1. ⽅便内存释放
    代码一:
    示意图为连续内存,只是为了区分划分为了几块,红色部分为柔性数组调整大小的部分
    在这里插入图片描述
    代码二:
    示意图为连续内存,只是为了区分划分为了几块,红色部分为柔性数组调整大小的部分
    在这里插入图片描述
    代码一的空间是一次性在堆区上开辟的,而代码二是先开辟结构体的空间,再开辟柔性数组的空间的,而既然是开辟的空间,就需要使用free来释放,否则有可能导致内存泄漏,而代码一只需要一次释放,而代码二中结构体往往知道释放,但是结构体成员也需要释放容易被忽视,所以,如果我们把结构体的内存以及其成员要的内存⼀次性分配好了,并返回给⼀个结构体指针,做⼀次free就可以把所有的内存也给释放掉

2.这样有利于访问速度
代码一中是一块连续的内存,连续的内存有益于提⾼访问速度,也有益于减少内存碎⽚。(只是相较于代码二速度会快一点,其实,我个⼈觉得也没多⾼了,反正你跑不了要⽤做偏移量的加法来寻址)

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

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

相关文章

【EI会议征稿】第三届电子信息工程、大数据与计算机技术国际学术会议(EIBDCT 2024)

第三届电子信息工程、大数据与计算机技术国际学术会议&#xff08;EIBDCT 2024&#xff09; 2024 3rd International Conference on Electronic Information Engineering, Big Data and Computer Technology 第三届电子信息工程、大数据与计算机技术国际学术会议&#xff08;…

小狐狸GPT付费2.4.9弹窗版学习源码介绍

小狐狸GPT付费2.4.9弹窗版学习源码是一套基于GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型的开源代码库&#xff0c;旨在帮助开发者快速构建和训练自己的语言模型。该源码集成了多个先进的自然语言处理技术&#xff0c;包括预训练、微调、对话生成等&am…

云服务领取证书,注册域名,实现nginx服务配置证书

目录 1.登录网址腾讯云 2.腾讯云注册域名 3.实名认证&#xff0c;上传信息 4.域名注册 5.领取证书 6.域名与证书绑定 7.下载证书 8.设置环境 9.域名解析 10. 本地域名解析 11.上传证书到目录 12.nginx配置文件做地址重写到证书域名 13.配置证书conf 14.设置index…

磁盘坏道修复工具-是一款非常方便实用的磁盘坏道修复软件-供大家学习研究参考

1、支持磁盘数据擦除。 2、杜绝因硬盘坏道&#xff0c;而产生个人隐私数据泄露的问题。 3、支持对该磁盘格式化。 下载&#xff1a;https://download.csdn.net/download/weixin_43097956/88625682

JavaScript自执行函数:用途、好处

JavaScript中的自执行函数是一个常见的编程技巧&#xff0c;它可以在特定的场景中发挥重要作用。本文将介绍自执行函数的用途、好处&#xff0c;并提供代码示例进行说明。 引言 在JavaScript编程中&#xff0c;自执行函数是一种特殊的函数调用方式&#xff0c;它能够在定义后…

Python中的列表推导式

使用列表推导式可以快速生成一个列表&#xff0c;或者根据某个列表生成满足指定需求的列表。列表推导式通常有以下几种常用的语法格式&#xff1a; &#xff08;1&#xff09;生成指定范围的数值列表&#xff0c;语法格式如下&#xff1a; list[Expression for var in range] …

【贪心】LeetCode-406. 根据身高重建队列

406. 根据身高重建队列。 假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个身高大于或等于 hi 的人。 请你重新…

关于“Python”的核心知识点整理大全22

目录 ​编辑 9.4.2 在一个模块中存储多个类 虽然同一个模块中的类之间应存在某种相关性&#xff0c;但可根据需要在一个模块中存储任意数量的 类。类Battery和ElectricCar都可帮助模拟汽车&#xff0c;因此下面将它们都加入模块car.py中&#xff1a; car.py my_electric_car…

焦虑,其实是你自愿选择的

如果一个人想要焦虑&#xff0c;他可以永远焦虑下去 从上学&#xff0c;到找工作&#xff0c;从买房到结婚生娃&#xff0c;他总是可以选择用自己的头脑去过度思考未来还没有发生的事情&#xff0c;从而让自己无限焦虑下去&#xff0c;直到生命终结。 我们的生命是存在于当下…

技术点:实现大文件上传

大文件上传 实现思路 对于大文件上传考虑到上传时间太久、超出浏览器响应时间、提高上传效率、优化上传用户体验等问题进行了深入探讨&#xff0c;以下初略罗列各个知识点的实现思路&#xff1a; 大文件上传对文件本身进行了文件流内容 Blob 的分割&#xff0c;使用 Blob.pr…

基于 Gin 的 HTTP 代理上网行为记录 demo

前言: 前端时间写了好几篇使用 Gin 框架来做 HTTP 代理 demo 的文章&#xff0c;然后就想着做一个记录上网行为的小工具&#xff0c;就是简单记录看看平时访问了什么网站&#xff08;基于隧道代理的&#xff0c;不是中间人代理&#xff0c;所以只能记录去了哪里&#xff0c;不能…

wps左上角有绿色小三角的数字如何求和

1.这个状态是求和不了的&#xff0c;使用求和公式求出来的也是0 2.进行如下操作 3.转换好后 则可以求和成功了

使用JavaScript转换图片格式

我们可以在现代浏览器中直接转换图片和格式&#xff0c;不需要上传服务器或者使用服务器脚本。 HTML <!-- 文件上传控件 --> <input type"file" id"fileInput" accept"image/*" /><!-- 输出格式选择 --> <select id"…

sns 查看pandas 数据对比

一 对比其中两列数据的方式 import seaborn as snssns.kdeplot(data[charge], shade True, hue data[sex]) sns.kdeplot 是 Seaborn 库中用于绘制核密度估计图&#xff08;Kernel Density Estimate&#xff0c;简称 KDE 图&#xff09;的函数。核密度估计是一种非参数统计方…

redis基本用法学习(主要数据类型)

redis官网教程中介绍有三种方式连接redis&#xff1a;命令行、gui工具和编程连接&#xff1a;   命令行方式主要是在命令行中输入redis-cli后&#xff0c;通过命令方式与redis服务进行交互&#xff0c;支持两种模式&#xff1a;REPL模式&#xff08;简单的交互式的编程环境&a…

深度学习 Day16——P5运动鞋识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 文章目录 前言1 我的环境2 代码实现与执行结果2.1 前期准备2.1.1 引入库2.1.2 设置GPU&#xff08;如果设备上支持GPU就使用GPU,否则使用C…

【C++配置yaml】yaml-cpp使用

yaml-cpp 》》参考资料1 》》参考资料2 文章目录 yaml-cpp下载安装yaml-cpp使用Nodenode的增改查删Node 相关APIyaml文件解析 下载安装 安装yaml-cpp git clone https://github.com/jbeder/yaml-cpp.git cd yaml-cpp mkdir build && cd build cmake .. && m…

【Qt QML 入门】TextArea

TextArea也是一个多行文本编辑器。TextArea相比texttedit&#xff0c;增加了占位符文本&#xff0c;并添加了样式定义。 import QtQuick import QtQuick.Window import QtQuick.ControlsWindow {id: winwidth: 800height: 600visible: trueTextArea {id: taanchors.centerIn: …

解决Visual Studio 各版本都出现新建项目后解决方案下没有文件和项目问题

一步一步创建C#控制台应用程序也会出错&#xff0c;这个你可能不会相信&#xff0c;我就遇到了这么一次&#xff0c;就在刚刚&#xff0c;是的&#xff0c;我都不敢相信&#xff0c;用了这么多年的新建一个控制台程序居然不正常了。新建完毕发现里面什么都没有&#xff0c;除了…

飞天使-docker知识点10-docker总结

文章目录 docker 知识点汇总docker chatgpt解释学习路线 docker 知识点汇总 docker 基础用法 docker 镜像基础用法 docker 容器网络 docker 存储卷 dockerfile docker仓库 harbor docker-compose docker chatgpt解释学习路线 学习Docker可以帮助你了解容器化技术&#xff0c…