🐱🏍1.柔性数组的概念:
也许你从没有听说过柔性数组(flexible array)的概念,但是它确实存在的;
在C99中,结构体的最后一个元素允许是未知大小的数组,这就叫【柔性数组】成员;
例如:
struct S
{
int n;
int arr[]; //柔性数组成员
}
🐱🏍2.柔性数组的特点
- 结构体中的柔性数组成员前面必须至少有一位成员变量;
- sizeof()函数计算结构体大小时,是不包括柔性数组的成员所占内存大小的;
- 包含柔性数组成员的结构最好用malloc()函数进行动态分配内存,并且分配的内存应该大于结构体的大小,以适应于柔性数组的预期大小;
🐱🏍3.柔性数组的使用
struct S
{
int n;
int arr;
}
int main()
{
struct S* ps = (struct S*)malloc(sizeof(S)+100*sizeof(int));
ps->n =10;
int i;
for(i = 0;i<10;i++)
{
ps->arr[i] = i;
}
free(ps)
return 0;
}
注:此时结构体内存都是在堆上开辟的一个连续的内存空间;
//想一想,如果我们不用柔性数组,直接用一个指针可以吗?
struct S
{
int n;
int *p;
}
//好像两种方法都可以,那我们为什么要用柔性数组呢?
//我们具体在使用上面的结构体时
int main()
{
struct S* ps = (struct S*) malloc(sizeof(S)); //为结构体分配空间
/*
此时在堆上开辟了一个空间里面包含:
变量n 和 p,而p变量是一个指针变量,我们要使用它又得给它在堆上开辟空间;
*/
ps->n = 10;
ps->p = (int*)malloc(10*sizeof(int)); //为结构体分配空间
return 0;
free(ps->p);
ps->p = NULL;
free(ps);
ps = NULL;
}
解析:
- 对比和柔性数组的方法,指针方式会造成一些内存碎片的浪费;
- 因为在堆上两次开辟内存,它可能并不是连续的一块内存;
- 这样就会导致两块内存之间存在着一些比较难以利用的不大不小的内存快,而且访问两次内存快也会降低访问速度;
🐱🏍5.柔性数组的优势
(1)方便内存释放
如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构返回给用户;用户调用free可以释放 结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事情;所以我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放;
(2)有利于提高访问速度
连续的内存有利于提高访问速度,有有益于减少内存碎片;
🐱🏍6.最后
关于柔性数组和指针的具体事例,请参考计算机专业大佬在2014年写的文章: