我们都熟悉了固定大小的数组的用法,不确定大小的数组却比较少听过,今天我就向大家介绍一下未知大小的数组——柔性数组。
1、柔性数组
在结构体中只能存在一个柔性数组,且必须是最后一个成员。
//写法一:
typedef struct st_type
{
int i;
int a[0]; //柔性数组成员
}typer_a;
//写法二:
typedef struct st_type
{
int i;
int a[ ]; //柔性数组成员
}type_a;
2、柔性数组的特点
- 结构体中的柔性数组成员前面必须至少一个其他成员(结构体中不能只含有柔性数组这一个成员,还得含有其它成员,并且这些成员都要在柔性数组之前,保证柔性数组是在最后一位)。
- sizeof(结构体)计算的结构体大小不包括柔性数组的大小(柔性数组的大小不确定,所以计算的肯定是结构体中除柔性数组以外的成员大小)。
- 包含柔性数组成员的结构体要malloc、realloc进行内存的动态分配,且分配的内存应该大于结构体的大小,以适应柔性数组的预期大小。
3、柔性数组的使用
#include<stdio.h>
#include<stdlib.h>
typedef struct st_type
{
int i;
int a[0]; //柔性数组成员
}type_a;
int main()
{
type_a *p = (type_a*)malloc(sizeof(type_a) + 10 * sizeof(int));//sizeof(type_a)计算的是结构体中除了柔型数组外其他成员所占字节的大小
if (p == NULL)
{
perror("malloc:");
return;
}
p->i = 100; //结构体中整形成员i的值为100
int i = 0;
for (i = 0; i < 10; i++)
{
p->a[i] = i;
}
for (i = 0; i < 10; i++)
{
printf("%d ", p->a[i]);
}
type_a *p2 = (type_a*)realloc(p, sizeof(type_a) +18*sizeof(int)); //sizeof(type_a)始终测的是结构体中除了柔性数组之外的其它成员所占字节的字节数,并且再增加了8*sizeof(int)个字节
if (p2 != NULL)
{
p = p2;
}
for (i = 10; i < 18; i++)
{
p->a[i] = i;
}
for (i = 10; i < 18; i++)
{
printf("%d ", p->a[i]);
}
free(p);//一定记得free
p = NULL;
}
4、柔性数组的优势
柔性数组比起普通数组来说具有能够改变大小的优点,那用指针也可以达到柔性数组的作用,如下代码所示:
#include<stdio.h>
#include<stdlib.h>
typedef struct st_type
{
int i;
int *p_a; //用指针代替柔性数组
}type_a;
int main()
{
type_a *p = (type_a*)malloc(sizeof(type_a)); //对结构体malloc是因为想要与使用柔性数组方法一致,都把结构体放在堆上
if (p == NULL)
{
perror("type_a malloc:");
return;
}
p->i = 10;
p->p_a = (int*)malloc(p->i * sizeof(int));
if (p->p_a==NULL)
{
perror("p->p_a malloc:");
return;
}
for (int i = 0; i < p->i; i++)
{
p->p_a[i] = i;
printf("%d ", p->p_a[i]);
}
return 0;
}
既然用指针也能实现柔性数组可以达到的效果,那么为什么要用柔性数组而不用指针?
有两点原因:
- 方便释放内存。当我们写一个给别人用的函数时,我们在这个函数里面进行了二次分配(第一次给结构体分配内存,第二次给指针分配内存),而别人却不知道我们作了二次分配,可能在free指针时会漏掉其中的一些内容,造成内存泄漏。
- 有利于访问速度。连续的内存有益于提高访问速度,也有益于减少内存碎片。(用指针会进行二次分配内存,但两次分配的内存可能不是在一起,中间可能浪费了不少的内存)