柔型数组

123 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

柔型数组

你听说过柔性数组吗?从这个名字我们就能感受到,这个数组有多么的不一般。

柔性数组简介

C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员。

如:

struct S {
	int a;
	int arr[0];
};

或者

struct S {
	int a;
	int arr[];
};

这种情况用于有些编译器报错的情况下;

柔型数组的特点

1、结构中的柔性数组成员前面必须至少有一个其他成员。
2、sizeof 返回的结构大小不包括柔性数组的内存。

例如:

struct S {
	int a;
	int arr[0];
};
int main()
{
	struct S s;
	printf("%d", sizeof(s));//计算包含柔型数组的结构体大小
	return 0;
}

输出结果为4,可见:结构大小不包含柔型数组的大小(毕竟柔型数组是0长度的数组)

3、包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

如:

struct S* ptr = (struct S*)malloc(sizeof(s) + 10 *sizeof(int));

在原有的结构体变量s的大小基础上,增加了10个int大小的空间;

柔型数组的优势

struct S {
	int a;
	int* p;
}*s;
int main()
{
	s = (struct S*)malloc(sizeof(struct S));
	if (s != NULL)
	{
		s->p = (int*)malloc(40);
		free(s->p);
		s->p = NULL;
		free(s);
		s = NULL;
	}
	return 0;}

这种方法相较于使用柔型数组:

struct S* ptr = (struct S*)malloc(sizeof(s) + 10 *sizeof(int));

能完成同样的任务,但是使用柔型数组有两个好处:

第一个好处是:方便内存释放

如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。 简单的说,使用第二种方法需要free释放两次,而且释放的顺序也有要求,而使用柔型数组只需要free释放一次;

第二个好处是︰这样有利于访问速度.

连续的内存有益于提高访问速度,也有益于减少内存碎片。 使用柔型数组只需要malloc一次,也就是说,开辟一个空间,而第二种方法需要两次malloc,开辟两个空间,而这两个空间大概率不是连在一起的,这种情况会造成访问速度下降。为什么? CPU获取数据的方式大概是这样的:在这里插入图片描述 CPU从寄存器获取数据,而寄存器中的数据从cache中获取,cache的数据从内存中获取,但是由于局部性原理:从内存中的某个位置访问数据,所访问的存储单元都趋于聚集在一个较小的连续区域中。这就导致第二种方法的访问速度不如柔型数组方式的访问速度。因为利用柔型数组只开辟了一个连续的空间,但是第二种方法使用两次malloc开辟了两个空间,而且这两个空间大概率不连续,导致访问速度下降; 此外,开辟两个空间会导致出现内存碎片;