【C语言进阶】你听说过柔性数组吗?

news2024/11/16 0:33:31

在这里插入图片描述

👦个人主页:@Weraphael
✍🏻作者简介:目前是C语言学习者
✈️专栏:C语言航路
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注


前言

说起数组,一维数组、二维数组、字符数组、整型数组和浮点型数组,我相信大家并不陌生吧,今天我们一起看看柔性数组!

目录

  • 前言
  • 一、柔性数组的概念和定义
  • 二、柔性数组的特点
  • 三、柔性数组的使用
  • 四、柔性数组的优势

一、柔性数组的概念和定义

在C99中,结构中的最后一个元素允许是未知大小的数组,我们把这样的数组称为柔性数组成员。

【定义】

struct S
{
	int i;
	int a[]; //柔性数组
};

若有些编译器无法编译,可以改成以下这种:

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

二、柔性数组的特点

  • 结构中的柔性数组前必须至少有一个其他成员
    在这里插入图片描述
  • sizeof返回的这种结构大小不包括柔性数组的内存
    在这里插入图片描述
  • 包含柔性数组成员的结构用malloc函数进行动态内存分配,并且分配的内存应该大于结构体大小,以适应柔性数组的预期大小
    在这里插入图片描述

三、柔性数组的使用

动态内存开辟函数讲解:传送门

#include <stdio.h>
#include <stdlib.h>
struct S
{
	int i;
	char a[];
};
int main()
{
	//包含柔性数组成员的结构用`malloc`函数进行动态内存分配
	//并且分配的内存应该大于结构体大小
	struct S* sp = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(char));
	//若sp为空指针,说明开辟动态内存失败
	if (sp == NULL)
	{
		return 1;
	}
	//否则开辟成功
	//使用
	sp->i = 100;
	for (int i = 0; i < 10; i++)
	{
		sp->a[i] = 'x';
	}
	//打印
	for (int i = 0; i < 10; i++)
	{
		printf("%c ", sp->a[i]);
	}
	//释放
	free(sp);
	sp = NULL;

	return 0;
}

在这里插入图片描述

甚至还能扩容realloc

#include <stdio.h>
#include <stdlib.h>
struct S
{
	int i;
	char a[];
};
int main()
{
	//包含柔性数组成员的结构用`malloc`函数进行动态内存分配
	//并且分配的内存应该大于结构体大小
	struct S* sp = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(char));
	//若sp为空指针,说明开辟动态内存失败
	if (sp == NULL)
	{
		return 1;
	}
	//否则开辟成功
	//使用
	sp->i = 100;
	for (int i = 0; i < 10; i++)
	{
		sp->a[i] = 'x';
	}
	//扩容(多加10字节的空间)
	struct S* p = (struct S *)realloc(sp, sizeof(struct S) + sizeof(char) * 20);
	//如果p为空指针说明扩容失败
	if (p == NULL)
	{
		return 1;
	}
	else
	{
		sp = p;
		p = NULL;
	}
	for (int i = 10; i < 20; i++)
	{
		sp->a[i] = 'w';
	}
	//打印
	printf("%d\n", sp->i);
	for (int i = 0; i < 20; i++)
	{
		printf("%c ", sp->a[i]);
	}
	

	return 0;
}

在这里插入图片描述

所以柔性数组在内存其实是这样的
在这里插入图片描述
它在内存是连续

四、柔性数组的优势

除【柔性数组的使用】样例以外,也可以设计成下面这样:

#include <stdio.h>
#include <stdlib.h>

struct  S
{
	int i;
	char* a;
};

int main()
{
	//为结构体开辟空间
	struct S* sp = (struct S*)malloc(sizeof(struct S));
	//若sp = NULL,说明开辟失败
	if (sp == NULL)
	{
		return 1;
	}
	//否则开辟成功
	//使用内存空间
	sp->i = 100;
	//为char* a开辟10个字节空间
	sp->a = (char*)malloc(sizeof(char) * 10);
	//使用
	for (int i = 0; i < 10; i++)
	{
		sp->a[i] = 'w';
	}
	//或者还能为char* a扩容
	char* p = (char*)realloc(sp->a, 20 * sizeof(char));
	if (p == NULL)
	{
		return 1;
	}
	else
	{
		sp->a = p;
		p = NULL;
	}
	//使用扩容的空间
	for (int i = 10; i < 20; i++)
	{
		sp->a[i] = 'J';
	}
	//打印
	printf("int i = %d\n", sp->i);
	for (int i = 0; i < 20; i++)
	{
		printf("%c ", sp->a[i]);
	}
	//释放空间
	free(sp->a);
	sp->a = NULL;
	free(sp);
	sp = NULL;
	return 0;
}

在这里插入图片描述

一个常见的问题:为什么要先释放sp->a的内存空间

  • 首先程序是先为结构体开辟空间
    在这里插入图片描述
  • 接着又为char*开辟空间
    在这里插入图片描述
    所以,若先对sp释放空间,到后面就不能通过sp找到char* c开辟的空间

柔性数组好处的总结:

  • 对于柔性数组来说,开辟空间(malloc)只需要一个,释放空间(free)也只需要一次,且内存空间是连续的,而对于上面的代码来说,开辟空间需要二次,释放空间也同样需要二次,且内存空间是不连续的。所以它第一个好处是方便内存释放
  • 连续的内存有益于提高访问速度

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

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

相关文章

ChatGPT入门案例|商务智能对话客服(三)

本篇介绍智能客服的基本功能架构和基本概念&#xff0c;并利用对话流技术构建商务智能应用。 01、商务智能客服功能结构 互联网的发展已经深入到社会的各个方面&#xff0c;智能化发展已经成为社会发展的大趋势。在大数据和互联网时代&#xff0c;企业和组织愈加重视客户沟通…

波奇学数据结构:时间复杂度和空间复杂度

数据结构&#xff1a;计算机存储&#xff0c;组织数据方式。数据之间存在多种特定关系。时间复杂度&#xff1a;程序基本操作&#xff08;循环等&#xff09;执行的次数大O渐进法表示法用最高阶的项来表示&#xff0c;且常数变为1。F&#xff08;n&#xff09;3*n^22n1//F(n)为…

git基础使用

Git安装 去安装>> 正式开始 进入要管理的目录&#xff0c;执行命令 git init 查看管理目录下的状态 git status 注&#xff1a;新增文件和修改过后的文件都是红色 管理指定文件&#xff08;红变绿&#xff09; 指定文件&#xff1a;git add 文件名 当前目录下所有&…

【Python入门第十二天】Python 列表

Python 集合&#xff08;数组&#xff09; Python 编程语言中有四种集合数据类型&#xff1a; 列表&#xff08;List&#xff09;是一种有序和可更改的集合。允许重复的成员。元组&#xff08;Tuple&#xff09;是一种有序且不可更改的集合。允许重复的成员。集合&#xff08…

深度学习常用的python函数(一)

由于我只简单的学过python和pytorch&#xff0c;其中有很多函数的操作都还是一知半解的&#xff0c;其中有些函数经常见到&#xff0c;所以就打算记录下来。 1.zip zip(*a):针对单个可迭代对象压缩成n个元组&#xff0c;元组数量n等于min(a中元素的最小长度) a [(1, 2), (3…

springmvc网上商城购物每日推荐购买系统 java ssm

为了解决用户便捷地在网上购物&#xff0c;本文设计和开发了一个熙迪网上购买系统。本系统是基于web架构设计&#xff0c;SSM框架 &#xff0c;jsp技术的前台页面设计与实现&#xff0c;使用Mysql数据库管理&#xff0c;综合采用jsp模式来完成系统的相关功能。主要实现了管理员…

Linux中最基本常见命令总结

❤❤&#x1f49b;&#x1f49b;&#x1f49a;&#x1f49a;&#x1f499;&#x1f499;&#x1f49c;&#x1f49c;您的认可是对我最大的帮助&#x1f49c;&#x1f49c;&#x1f499;&#x1f499;&#x1f49a;&#x1f49a;&#x1f49b;&#x1f49b;❤❤ &#x1f90e;&…

【算法基础】堆⭐⭐⭐

一、堆 1. 堆的概念 堆(heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质: (1)堆中某个结点的值总是不大于或不小于其父结点的值; (2)堆总是一棵完全二叉树。 将根结点最大的堆叫做最大堆或大根堆,根结点…

以太网协议、arp协议、NAT协议、DNS协议

目录 数据链路层&#xff1a; 以太网协议&#xff1a; arp协议 1、arp协议格式 2、arp协议内容解释&#xff1a; arp缓存表 NAT协议&#xff1a;地址转换协议 1、作用&#xff1a;将网络数据当中的私网IP替换成为公网IP&#xff0c;或者将网络数据当中的公网IP替换为私网I…

大数据框架之Hadoop:MapReduce(二)Hadoop序列化

2.1序列化概述 1、什么是序列化 序列化就是把内存中的对象&#xff0c;转换成字节序列&#xff08;或其他数据传输协议&#xff09;以便于存储到磁盘&#xff08;持久化&#xff09;和网络传输。 反序列化就是将收到字节序列&#xff08;或其他数据传输协议&#xff09;或者…

TCP 的演化史-fast retransmit/recovery

工作原因要对一个 newreno 实现增加 sack 支持。尝试写了 3 天 C&#xff0c;同时一遍又一遍梳理 sack 标准演进。这些东西我早就了解&#xff0c;但涉及落地写实现&#xff0c;就得不断抠细节&#xff0c;试图写一个完备的实现。 这事有更简单的方法。根本没必要完全实现 RFC…

大型信息系统

一、大型信息系统二、信息系统的规划方法三、信息系统的规划工具 一、大型信息系统 信息系统规划&#xff08;也称为信息系统战略规划&#xff09;是一个组织有关信息系统建设与应用的全局性谋划&#xff0c;主要包括战略目标、策略和部署能内容。 信息化规划是企业信息化建设…

安全—08day

ApabilitiesapabilitiesLinux Capabilities线程的 capabilitiesPermitted 允许Effective 有效InheritableBoundingAmbient文件的 capabilitiesPermittedInheritableEffective运行 execve() 后 capabilities 的变化案例分析方法一、依次执行如下命令方法二、iptables端口转发方案…

SAP ABAP GUI_DOWNLOAD中下载乱码的问题

1 GUI_DOWNLOAD 1.1 问题表现 GUI_DOWNLOAD在应用当中有时会导致输出的文件在某些电脑正常显示&#xff0c;在某些电脑乱码显示。这个固然是由于各个电脑系统配置有差异&#xff0c;但是我们可以在应用该函数时就排除该差异来保证任意台电脑正常显示输出的文件。 如下…

英语基础-定语从句的特殊用法及写作应用

1. 定语从句的引导词省略的情况 1. that 引导定语从句&#xff0c;从句中缺宾语/表语&#xff0c;that可省略&#xff1b; This is the book that he likes. I like the shirt that you gave me. We do not agree on the plan that you make. China is not the country th…

论文浅尝 | SpCQL: 一个自然语言转换Cypher的语义解析数据集

笔记整理&#xff1a;郭爱博&#xff0c;国防科技大学博士论文发表会议&#xff1a;The 31th ACM International Conference on Information and Knowledge Management&#xff0c;CIKM 2022动机随着社交、电子商务、金融等行业的快速发展&#xff0c;现实世界编织出一张庞大而…

测试人员为什么也要学习Linux操作系统

我相信能够看到这篇文章的你&#xff0c;一定是对计算机感兴趣、想要增加技能从而为以后加薪打基础。今天&#xff0c;我就和大家谈谈我对为什么要学习 Linux 系统的看法。我将从如下这三个方面谈我的看法。 巩固基础知识 做一个合格的软件工程师 学以致用 1. 巩固基础知识 …

2023年美国大学生数学建模C题:预测Wordle结果建模详解+模型代码

目录 前言 一、题目理解 背景 解析 字段含义&#xff1a; 建模要求 二、建模思路 灰色预测&#xff1a; ​编辑 二次指数平滑法&#xff1a; person相关性 只希望各位以后遇到建模比赛可以艾特认识一下我&#xff0c;我可以提供免费的思路和部分源码&#xff0c;以后…

字符设备驱动基础(一)

目录 一、Linux内核对设备的分类 linux的文件种类&#xff1a; Linux内核按驱动程序实现模型框架的不同&#xff0c;将设备分为三类&#xff1a; 总体框架图&#xff1a; 二、设备号------内核中同类设备的区分 三、申请和注销设备号 四、函数指针复习 4.1、 内存四区 …

ACM数论 裴蜀定理(贝祖定理)

一.内容定义 「裴蜀定理」&#xff0c;又称贝祖定理&#xff08;Bzouts lemma&#xff09;。是一个关于最大公约数的定理。其内容定义为&#xff1a;对于不全为零的任意整数 a 和 b&#xff0c;记二者的最大公约数为 g 即 gcd(a,b) g&#xff0c;则对于任意整数 x 和 y 都一定…