C语言——柔性数组

柔性数组概念:

这个概念你可能没听说过,但是这个概念确实存在,在C99中,结构体中最后一个成员允许是未知大小的数组,这就叫做【柔性数组】成员。

cpp 复制代码
struct S
{
	char c;
	int i;
	int arr[0];//未知大小的数组 - 柔性数组成员
};

有些编译器可能不支持上面的写法,可以改成:

cpp 复制代码
struct S
{
	char c;//1
	//3
	int i;//4
	int arr[];//未知大小的数组 - 柔性数组成员
};

柔性数组的特点:

结构中的柔性数组成员前面必须至少有一个其他成员
sizeof返回这种结构体大小不包括柔性数组成员的内存
包含柔性数组成员的结构用malloc进行内存分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

我们还是以刚刚上面的结构体为例:

根据内存对齐规则,这个结构如果不算柔性数组大小的话,的确是8,而我们可以看到,这里打印出来的也确实是8,所以我们可以理解第二条特点sizeof返回结构大小的时候不包括柔性数组的大小。

那么第一条特点也就可以解释了,倘若结构里面只有柔性数组的话,那么sizeof计算结构体大小,就没办法算了,所以结构里柔性数组的前面必须至少有一个其他类型的成员。

那么第三条特点的意思是,我们在为其开辟内存的时候是这样的:

我们定义一个结构变量指针用来接收,然后malloc出来的空间首先sizeof(struct S)代表先给char和int两个成员变量开辟空间,然后剩下的+20就是给柔性数组来开辟的,内存申请的不够了,就可以用realloc重新调整大小。

具体的代码实现是这样的:

cpp 复制代码
struct S
{
	char c;//1
	//3
	int i;//4
	int arr[];//未知大小的数组 - 柔性数组成员
};

int main(){
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 20);
	if (ps == NULL)
	{
		perror("malloc");
		return 1;
	}
	ps->c = 'w';
	ps->i = 100;
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		ps->arr[i] = i;
	}
	//打印
	for (i = 0; i < 5; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	//空间不够了
	struct S* ptr = (struct S*)realloc(ps, sizeof(struct S)+40);
	if (ptr != NULL)
	{
		ps = ptr;
	}
	else
	{
		perror("realloc");
		return 1;
	}
	//增容成功后,继续使用
	
	//释放
	free(ps);
	ps = NULL;

	return 0;
}

上面的例子就是对结构里有柔性数组的该如何进行调整,malloc以及realloc,还有即使打印使用的时候。

但是如果我们在柔性数组那里换成指针是不是也一样可以达到空间的可大可小的效果呢?

例如这样的代码:

cpp 复制代码
struct s
{
	char c;
	int i;
	int* data;
};


int main()
{
	struct s* ps = (struct s*)malloc(sizeof(struct s));
	if (ps == NULL)
	{
		perror("malloc1");
		return 1;
	}
	ps->c = 'w';
	ps->i = 100;
	ps->data = (int*)malloc(20);
	if (ps->data == NULL)
	{
		perror("malloc2");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		ps->data[i] = i;
	}
	for (i = 0; i < 5; i++)
	{
		printf("%d ", ps->data[i]);
	}
	//空间不够了,增容
	int* ptr = (int*)realloc(ps->data, 40);
	if (ptr == NULL)
	{
		perror("realloc");
		return 1;
	}
	else
	{
		ps->data = ptr;
	}
	/*增容成功就使用
	...
	释放*/
	free(ps->data);
	ps->data = NULL;
	free(ps);
	ps = NULL;

	return 0;
}

我们这里结构里放了一个指针变量成员int* data,而我们再用malloc函数申请空间并让data指向这个空间也就达到了和柔性数组一样的效果。只不过我们这里需要malloc两次:

当然也需要释放两次:


那么既然这两个代码实现的效果一样,那么哪个更好一点呢?🤔🤔🤔

答案是:第一个会更好一点。(带有柔性数组)

好处1:方便内存释放

第一个只用申请一次,而第二个则需要申请两次。

好处2:有利于访问速度

一次申请空间,空间内存一定是连续的,但是两次申请空间的话,就不一定是连续的了,内存之间就有可能存在缝隙,那么这些缝隙,也就有可能影响访问速度。(但我个人觉得其实也没多高)。

相关推荐
brhhh_sehe14 分钟前
重生之我在异世界学编程之C语言:深入文件操作篇(下)
android·c语言·网络
Bucai_不才18 分钟前
【C++】初识C++之C语言加入光荣的进化(上)
c语言·c++·面向对象
蹉跎x34 分钟前
力扣1358. 包含所有三种字符的子字符串数目
数据结构·算法·leetcode·职场和发展
雨颜纸伞(hzs)43 分钟前
C语言介绍
c语言·开发语言·软件工程
巫师不要去魔法部乱说2 小时前
PyCharm专项训练4 最小生成树算法
算法·pycharm
IT猿手2 小时前
最新高性能多目标优化算法:多目标麋鹿优化算法(MOEHO)求解GLSMOP1-GLSMOP9及工程应用---盘式制动器设计,提供完整MATLAB代码
开发语言·算法·机器学习·matlab·强化学习
阿七想学习2 小时前
数据结构《排序》
java·数据结构·学习·算法·排序算法
a0023450012 小时前
判断矩阵是否为上三角矩阵
c语言
王老师青少年编程2 小时前
gesp(二级)(12)洛谷:B3955:[GESP202403 二级] 小杨的日字矩阵
c++·算法·矩阵·gesp·csp·信奥赛
Kenneth風车3 小时前
【机器学习(九)】分类和回归任务-多层感知机(Multilayer Perceptron,MLP)算法-Sentosa_DSML社区版 (1)111
算法·机器学习·分类