C语言柔性数组介绍

柔性数组

也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的。C99中,结构体中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。

//写法1
typedef struct st_type
{
	int i;
	int a[0];//柔性数组成员,大小未知
}type_a;

//写法2
typedef struct st_type
{
	int i;
	int a[];//柔性数组成员,大小未知
}type_a;

柔性数组的特点:

  • 结构中的柔性数组成员前面必须至少有一个其他成员
  • sizeof返回的这种结构大小不包括柔性数组的内存。
  • 包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
typedef struct st_type
{
	int i;	 //4
	int a[0];//柔性数组成员
}type_a;
int main()
{
	printf("%d\n"sizeof(type_a));	//输出的是4
    return 0;
}

柔性数组的动态申请内存和使用

typedef struct S
{
	int i;
	int arr[0];	//柔性数组
};
int main()
{
	//用malloc动态分配内存,期望arr的大小是10个整型
	struct S* p = (struct S*)malloc(sizeof(struct S)+10*sizeof(int));	//申请空间:4(i)+10*4(arr) = 44
    //使用...
    p->i = 10;
    for(int i = 0;i<10;i++)
    {
        p->arr[i] = i;		//对柔性数组赋值
	}
    //增容
    struct S* ptr = (struct S*)realloc(p,sizeof(struct S)+20*sizeof(int));
    if(ptr != NULL)
    {
        p = ptr;
	}
    //使用增容后的空间...
    //释放
    free(p);
    p = NULL;
    return 0;
}

用普通代码实现柔性数组的功能

//实现柔性数组相同功能
struct S
{
	int n;
	int* arr;
};
int main()
{
	struct S* p = (struct S*)malloc(sizeof(struct S));
	if (p == NULL)
	{
		return 1;
	}
	p->n = 10;
	p->arr = (int*)malloc(10 * sizeof(int));		//对指针arr再进行动态空间分配
	if (p->arr == NULL)
	{
		return 1;
	}
    //使用
	for (int i = 0; i < 10; i++)
	{
		p->arr[i] = i;
	}
	//增容
	int*  ptr = (int*)realloc(p->arr, 20 * sizeof(int));
	if (ptr != NULL)
	{
		p->arr = ptr;
	}
	free(p->arr);		//先释放arr指针指向的动态申请空间
	p->arr = NULL;
	free(p);		//再释放整个结构体的空间,如果先释放结构体的空间,指针arr被释放了,则arr指向的空间就找不到了
	p = NULL;
    return 0;
}

普通代码实现相同功能与柔性数组的比较

  1. 普通代码需要两次malloc与free,比较容易出错,而柔性数组只需要一次malloc与free,方便内存的申请与释放
  2. 多次malloc在堆上申请空间时,会产生内存碎片,内存碎片被再次利用的概率小,会造成内存利用率降低(这里引申出软件设计上的内存池概念:在内存池里已经统一申请了多块空间,程序需要时直接拿去用就可以,用完后还回来,再统一释放,做到对内存的统一管理)
  3. 空间局部性:一块内存被访问后,其周边的内存很大概率会被再次访问;所以柔性数组在一次性malloc时变量的内存是连续的,对内存的访问速度一定程度上比较快,而多次malloc的内存空间可能是不连续的,此时对内存的访问效率会有一定影响

你可能感兴趣的:(C语言,c语言)