我们都知道定义数组的时候必须规定他的大小。
Int a[10];
而 a[0];a[];这种定义是不行的
但在C语言的官方标准第二版里允许了在结构体里定义一个未知大小的数组
Typedef truct _August
{
int a_len;
int a_array[];
}aug;
在August结构体里我们定义了一个未知大小的int型数组;该数组允许之后不断添加成员;
这种数组叫做柔性数组;
我们定义一个该结构体的变量a,可以看到a的大小为4;
aug a;
sizeof(a)==4;
下面是他们在内存中的存储情况
这种结构看似方便,C语言给你开了一个权限,但你要避免柔性数组在增加的时候侵犯到他人空间;
我们知道栈中使用时是连续的分配地址,按高地址到低地址依次往下使用;
如果在栈中定义
aug a;
系统自动给a分配4个字节的空间
a之后的地址马上分配给其他变量或者代码;
当你给柔性数组赋值的时候:
a.a_array[0]=1;
它必然侵犯到其他人的空间;
编译的时候是不会报错;
但在运行该程序的时候则会提示段错误。
而堆中或者全局变量区里使用时地址是随机分配的。
当你给柔性数组赋值时:
a.a_array[0]=1;
他可能会侵犯到他人空间;
编译时不会报错;
程序运行时运气不好就会出现段错误。
这样想来柔性数组有点名不副实;
其实只是万事俱备,只欠东风;
如果说柔性数组是铁锁连舟;
那么堆则是它的赤壁;
realloc()是它的东风;
只有在堆中使用柔性数组才是用对了地方
首先我们开辟一个aug类型的空间;
aug *a2=(aug *)malloc(sizeof(aug)+sizeof(int)*10);
a2->len=10;
sieof(aug)的空间是用来存放该结构体的成员;
sizeof(int)*10的空间是用来存放该结构里的柔性数组;
我们预测柔性数组可能会用到10个成员,并用len记录我们的预测;
当使用时空间不够时,我们利用realloc来给他延续一段空间
max指当前要用到的数组下标
while ( max >= a2->len)
{
a2->len+=10;
a2=realloc(a2,sizeof(aug)+sizeof(int)*a2->len);
}
realloc延续空间可能会改变在堆中存的首地址;
因此如果有除了a2以外的其他指针还指向该空间,应事设为NULL;
当延续成功后再指向他;