【C语言】零长度数组(可变数组,柔性数组)

零长度数组又称可变数组,柔性数组,它是在C99中才定义的,所以有些编译器可能还不支持,我这里使用的是VS编译器。那现在就来让我们一起了解学习一下柔性数组吧!

一,什么是柔性数组?

在C99中,结构体最后一个元素允许是可调整大小的数组,这就叫做柔性数组的成员。例如:

struct S
{
	int n;
	int arr[0];//这就是可变数组(柔性数组,0长度数组)---可以调整大小
};

有些编译器可能不支持这么写,可以改成:

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

二,柔性数组的特点

1.结构体中柔性数组成员前面至少有一个其它成员;
2.sizeof用于计算所占内存大小的(单位:字节),当sizeof计算这种结构体的大小时,不会包括柔性数组的大小(下面会举例);
3.包含柔性数组成员的结构体用malloc函数()进行动态内存的分配,并且分配的大小是:结构体的大小+柔性数组的大小。

#include<stdio.h>
#include<stdlib.h>
struct S
{
	int n;//整型是4个字节
	int arr[0];//柔性数组
	//int arr[];
};
int main()
{
	//创建结构体变量
	struct S s;
	//计算结构体变量s的大小
	//结果为4个字节,所以在sizeof在计算包含柔性数组的结构体时
	//并不包含柔性数组的大小
	printf("%d\n", sizeof(s));//4
}

三,柔性数组的使用

#include<stdio.h>
#include<stdio.h>
struct S//类型
{
	int n;
	int arr[0];
};
int main()
{
	//用malloc函数开辟动态内存空间
	//注意指向动态内存起始地址的指针为struct S*类型
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int));//这里给柔性数组开辟了5个整型的大小
	ps->n = 100;
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		ps->arr[i] = i;//0 1 2 3 4
	}
	//这个时候我又觉得空间不够,我想再开辟5个整型的空间
	//所以我们利用realloc函数重新调整柔性数组的空间大小
	//realloc函数的学习请至我的博客
	struct S* str = realloc(ps, 44);
	//判断是否开辟成功
	if (str != NULL)
	{
		ps = str;
	}
	//利用这块新开辟的44个字节的空间
	for (i = 5; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	//记得动态内存函数调用完毕后,要释放空间,并把指向动态内存的指针置为空
	free(ps);
	ps = NULL;

	return 0;
}

柔性数组图解(使用柔性数组的解析在代码的注释中)
在这里插入图片描述

四,为什么存在柔性数组?

我们来看一个代码,这个代码不用柔性数组也一样可以完成以上的功能。那么为什么还存在柔性数组(可变数组,零长度数组)这个概念呢?

#include<stdio.h>
#include<stdlib.h>
struct S
{
	int n;
	int* arr;
};
int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	ps->arr = (int*)malloc(5 * sizeof(int));
	int i;
	for (i = 0; i < 5; i++)
	{
		ps->arr[i] = i;
	}
	//调整大小
	int* str = realloc(ps->arr, 10 * sizeof(int));
	if (str != NULL)
	{
		//注意这里是ps->arr(才是int*的指针),而不是ps
		ps->arr = str;
	}
	for (i = 5; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	//注意要先free(pa->arr);才能free(ps);
	free(ps->arr);
	ps->arr = NULL;
	free(ps);
	ps = NULL;

	return 0;
}

原因:
上面用指针实现的代码,用了malloc两次,两次开辟动态内存空间,而且这两块内存还不一定连续,这样就会有很多内存碎片,导致内存浪费。而且还要释放两次空间,并且要先释放ps->arr,才能释放ps,所以很容易导致错误。而柔性数组只需要开辟一次动态内存空间,并且内存是连续的,有利于提高访问速度,减少内存碎片。

C语言中,我们可以使用冒泡排序、选择排序或插入排序等算法对任意长度数组进行排序。 首先,我们可以使用冒泡排序算法。冒泡排序是一种基本的排序算法,它依次比较数组中相邻的两个元素,并根据大小交换它们的位置,直到整个数组排序完成。 其次,我们可以使用选择排序算法。选择排序也是一种基本的排序算法,它每次从剩余的未排序部分选择最小的元素,并将其放置在已排序部分的末尾,直到整个数组排序完成。 最后,我们可以使用插入排序算法。插入排序是一种简单直观的排序算法,它将数组分为已排序部分和未排序部分,然后将未排序部分中的元素依次插入到已排序部分的适当位置,直到整个数组排序完成。 无论是哪种算法,我们可以通过使用循环语句和条件语句来实现。我们需要遍历数组中的元素,并比较它们的大小来决定它们的位置。通过多次迭代,我们可以逐步完成排序过程。 需要注意的是,在编写排序算法时,我们应该考虑边界条件、异常情况和性能优化。例如,我们需要确保数组不为空且长度大于1,以避免不必要的运算。另外,可以使用适当的优化技巧,例如减少无效交换和比较次数,以提高排序的效率。 总之,无论数组长度多长,我们都可以使用不同的排序算法对其进行排序。只需要合理使用循环和条件语句,注意边界条件和性能优化,就可以实现对任意长度数组的排序。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_麦子熟了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值