C语言之认识柔性数组(flexible array)

在学习之前,我们首先要了解柔性数组是放在结构体当中的,知道这一点,我们就开始今天的学习吧!


1.柔性数组的声明

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

这里的结构是结构体

我们看个代码了解:

cs 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

//柔性数组的声明

typedef struct S
{
	int n;
	char c;
	char arr[0];//它就是柔性数组
	//还有另一种写法,就是char arr[],这两种写法在我们vs中都是不会出错的
}S;
int main()
{	
	//printf("%zd\n", sizeof(S));
	return 0;

}

2.柔性数组的特点

1.结构中的柔性数组成员前面必须至少有一个其他成员

2.sizeof返回的这种结果大小不包括柔性数组的内存

3.包含柔性数组成员的结构用malloc函数进行内存的动态分配,并且分配的内存应该大于结构体的大小,以适应柔性数组的预期大小

我们可以验证一下:

我们求一下这个结构体的大小:

cs 复制代码
typedef struct S
{
	int n;
	char arr[];//它就是柔性数组
}S;
int main()
{
	printf("%zd\n", sizeof(S));
	return 0;
}

运行一下,我们发现它求出来结构体的大小是前面整型的大小,没有包含这个柔性数组的大小


我们再看一个代码来了解柔性数组的整体特性

cs 复制代码
typedef struct S
{
	int n;
	char arr[];//它就是柔性数组
}S;
int main()
{
	//未使用这个柔性数组前,计算一下这个结构体的总大小,和后面使用之后作比较
	//看看有什么不同
	printf("%d\n", sizeof(S));
	//我们为这个结构体成员和柔性数组成员分配动态内存空间
	S* pc = (S*)malloc(sizeof(char) * 10 + sizeof(S));
	if (pc == NULL)
	{
		perror("malloc");
		return 1;
	}
	//开始使用柔性数组
	pc->n = 100;
	int i = 1;
	for (i = 1; i <= 10; i++)
	{
		pc->arr[i] = i;
		printf("%d ", pc->arr[i]);
	}
	//如果空间不足,我们可以进行增容
	S* str = (S*)realloc(pc,sizeof(S) + sizeof(sizeof(char) * 20));
	if (str == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	pc = str;
	printf("\n");
	//在这里我们可以求一下现在结构体的大小,看它在使用了柔性数组之后
	//结构体的总大小是否发生了变化
	printf("%d\n", sizeof(S));
	//释放空间
	free(pc);
	pc = NULL;
	return 0;
}

我们运行查看一下结果

我们发现

1.结构体使用柔性数组前后,结构体总大小没有发生变化,都是4

2.我们使用别的办法也可以达到柔性数组所达到的效果,为什么还要存在柔性数组呢?

这就引出了我们下一个知识点,为什么存在柔性数组

3.为什么存在柔性数组

我们用别的办法实现一下这个柔性数组所实现的功能,对比着来看更能理解

cs 复制代码
typedef struct S
{
	int n;
	char* arr;
}S;

int main()
{
	printf("未动态开辟时内存大小:%zd\n", sizeof(S));
	//为整个结构体分配动态内存空间
	S* pc = (S*)malloc(sizeof(S));
	if (pc == NULL)
	{
		perror("malloc");
		return 1;
	}
	//使用这块空间
	pc->n = 100;
	//再用malloc为指针arr分配空间
	pc->arr = (char*)malloc(sizeof(char) * 10);
	if (pc->arr == NULL)
	{
		perror("malloc");
		return 1;
	}
	//使用给arr分配的这块空间
	int i = 0;
	for (i =0; i < 10; i++)
	{
		pc->arr[i] = 'Q';
		printf("%c ", pc->arr[i]);
	}
	printf("\n");
	printf("malloc这块空间后内存大小:%zd\n", sizeof(S));
	//对这块空间进行增容
	char* ptr = (char*)realloc(pc->arr, sizeof(char) * 20);
	if (ptr == NULL)
	{
		perror("realloc");
		return 1;
	}
	//使用增容后的空间
	ptr = pc->arr;
	for (i = 0; i < 10; i++)
	{
		pc->arr[i] = 'L';
		printf("%c ",pc->arr[i]);
	}
	printf("\n");
	printf("realloc这块空间后内存大小:%zd\n", sizeof(S));
	//释放空间
	free(pc->arr);
	pc->arr = NULL;
	free(pc);
	pc = NULL;
	return 0;
}

我们比较一下两种写法,它们可以达到一样的效果

但是

柔性数组:

1.malloc只需要开辟一次

2.free空间一次

3.开辟的空间是连续的

普通写法:

1.malloc两次

2.free两次

3.开辟的空间不一定连续

我们要知道malloc的次数越多,越容易处处,可能free顺序不对或者忘记free,造成内存泄漏;同时,内存碎片越多,没别利用的空间就越多,造成空间的浪费。

此时,我们就要知道存在即合理,柔性数组的存在是有一定的道理的。

接下来我们总结一下柔性数组的好处

4.柔性数组的好处

1.方便内存释放(我们在为什么存在柔性数组里已经分析过了)

2.有利于提高访问效率

连续的内存有益于提高访问速度,也有益于减少内存碎片


好了,这就是关于柔性数组的全部知识,大家要慢慢感悟,咱们下期再见!!!

相关推荐
思麟呀13 分钟前
C++11并发编程:call_once一次性执行+atomic原子类型+CAS无锁编程+自旋锁
linux·开发语言·jvm·c++·windows
码不停蹄的玄黓37 分钟前
Java 生产者-消费者模型详解
java·开发语言·python
LONGZETECH38 分钟前
软硬协同+故障注入:无人机仿真维修与操控仿真底层算法逻辑拆解
大数据·c语言·算法·3d·unity·无人机
爱讲故事的40 分钟前
操作系统第一讲复习:为什么学习操作系统,以及操作系统到底在做什么?
linux·开发语言·windows·学习·ubuntu·c#
笨蛋不要掉眼泪44 分钟前
Java并发编程:Executors框架类深度解析
java·开发语言·并发
zlinear数据采集卡1 小时前
SPI Flash存储电路深度解析:从芯片选型到ZLinear采集卡的实战设计
c语言·嵌入式硬件·自动化·硬件架构
_童年的回忆_1 小时前
【php】在linux下PHP安装amqp扩展
linux·开发语言·php
AIMath~2 小时前
python中的uv命令揭秘
开发语言·python·uv
弹简特2 小时前
【零基础学Python】06-Python模块和包、异常处理、文件常用操作
开发语言·python
x***r1512 小时前
Postman-win64-7.2.2-Setup安装步骤详解(附API接口测试与参数配置教程)
开发语言·lua