C语言---柔性数组

文章目录

  • 前言
  • 1. 柔性数组的特点
  • 2. 柔性数组的使用
  • 3. 为何选择柔性数组

前言

结构中最后一个元素允许是未知大小的数组,这个数组就是柔性数组。但结构中的柔性数组前面必须至少一个其他成员,柔性数组成员允许结构中包含一个大小可变的数组,sizeof返回的这种结构大小不包括柔性数组的内存。包含柔数组成员的结构用malloc函数进行内存的动态分配,且分配的内存应该大于结构的大小以适应柔性数组的预期大小。

柔性数组的定义:

struct test {
    short len;  // 必须至少有一个其它成员
    char arr[]; // 柔性数组必须是结构体最后一个成员(也可是其它类型,如:int、double、...)
};

1. 柔性数组的特点

  1. 结构中的柔性数组成员前面必须至少一个其他成员。
  2. sizeof 返回的这个结构体大小不包括柔性数组的内存。也就是使用sizeof计算这个结构体大小的时候,只会计算柔性数组之前的东西。
  3. 包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
typedef struct st_type
{
 int i;
 int a[0];//柔性数组成员
}type_a;
printf("%d\n", sizeof(type_a));//输出的是4

2. 柔性数组的使用

#include 
#include 

struct S
{
	int i;
	int arr[];
}s;
int main()
{
	//开辟动态内存
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));//为结构体申请动态内存空间

	//判断是否为空指针,开辟是否成功
	if (ps == NULL)
	{
		return 1;
	}
	//业务处理
	ps->i = 100;
	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	
	//释放:
	free(ps);
	ps = NULL;
	return 0;
}

对于这段代码,柔性数组成员arr,相当于获得了10个整型元素的连续空间。


3. 为何选择柔性数组

其实对于上面的柔性数组,我们可以换成指针来实现相同的功能:

struct S
{
	int i;
	int* arr;
}s;
int main()
{
	//开辟动态内存
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));//为结构体申请动态内存空间

	//判断是否为空指针,开辟是否成功
	if (ps == NULL)
	{
		return 1;
	}

	//为结构体内的指针arr再开辟一块动态内存:
	ps->arr = (int*)malloc(20 * sizeof(int));
	//判断是否为空指针:
	if (ps->arr == NULL)
	{
		return  1;
	}
	//业务处理
	ps->i = 100;
	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	
	//释放:先释放后开辟的那块
	free(ps->arr);
	ps->arr = NULL;
	free(ps);
	ps = NULL;
	return 0;
}

既然可以使用这样的指针来实现,为什么还要使用柔性数组呢?

  1. 方便内存释放:
    如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。
  2. 有利于访问速度:
    连续的内存有益于提高访问速度,也有益于减少内存碎片。

你可能感兴趣的:(C语言学习笔记,c语言)