今天突然看到一个比较特别的知识点——柔性数组。它是在C99中出现的一种特别的数组,具体是指结构体中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。
目录
1.柔性数组的定义
2.柔性数组的特点
3.柔性数组的使用举例
4.柔性数组的优点
1.柔性数组的定义
柔性数组定义的一般形式为:
typedef struct st_type
{
int i;
int a[0];//柔性数组成员
}type_a;//这里的typedef是重命名的意思,是把原来struct struct st_type命名为type_a,以方便使用
有些编译器会报错,我们可以改成下面这种定义方式。
typedef struct st_type
{
int i;
int a[ ];//柔性数组成员
}type_a;
2.柔性数组的特点
①结构中的柔性数组成员前面必须至少有一个其他成员。
②sizeof 返回的这种数据结构大小不包括柔性数组的内存。
③包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小,即malloc申请的空间应该是sizeof(结构体体变量)+柔性数组大小(用多少开辟多少)。
struct st_type
{int i;int *a;//柔性数组成员}int main()
{printf("%d\n", sizeof(st_type));//输出的是4return 0;
}
3.柔性数组的使用举例
#include <stdio.h>
#include <stdlib.h>
int main()
{int i = 0;type_a *p = (type_a*)malloc(sizeof(type_a)+100*sizeof(int));//在使用前一定要定义,这里图方便没有定义p->i = 100;for(i=0; i<100; i++){p->a[i] = i;} free(p);//动态开辟的内存,记得及时释放return 0;
}
4.柔性数组的优点
柔性数组是一个结构体的一个成员数组,在上面的例子中,整个结构体都是在堆上malloc出来的。此时,整个结构体都是存储在堆上一块连续的空间内,因为数组arr的大小是可以改变的,所以就叫柔性数组。但是实际上如果我们把柔性数组成员换成一个指针成员,然后通过malloc也是可以动态开辟空间的,如下图代码所示:
struct st_type
{int i;int *arr;//柔性数组成员}int main()
{struct st_type* ps = (struct st_type*)malloc(sizeof(struct st_type));if(ps == NULL){printf("malloc()->%s\n") , strerror(errno));return 1;}ps->arr = (int*)malloc(10 * sizeof(int));if(ps->arr == NULL){printf("2:malloc()->%s\n") , strerror(errno));return 1;}return 0;
}
上面指针arr在malloc后,即可当作数组使用。那么我们为什么要引入柔性数组呢?原因有以下两点:
①方便内存释放
使用时,柔性数组malloc一次,free一次;不使用柔性数组要malloc两次,free两次。如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返 回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。
②有利于提高访问速度
连续的内存有益于提高访问速度,也有益于减少内存碎片。