柔性数组
c语言并没有柔性数组这个概念,但他又是实际存在的,结构体中最后一个成员是数组,且未规定内存大小,即可理解为柔性数组
柔性数组的特点
1.结构体中柔性数组的成员前面至少有一个其他成员
2.sizeof计算结构体大小是不包含柔性数组的内存
3.包含柔性数组成员的结构应用malloc进行开辟内存空间,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小
1.
struct S
{
int a;
int arr[];//大小未知,有的写成int arr[0]也是可以的
};
此时arr就是一个柔性数组
2.
struct S
{
int a;
int arr[];
};
int main()
{
printf("%d", sizeof(s));//计算柔性数组的大小,是不包含柔性数组的,只计算它前面的变量
return 0;
}
运行的结果是
4
也就是不包括柔性数组的大小,只有他前面成员的大小
2.柔性数组应该用malloc进行开辟空间,而不是直接对其进行赋值
struct S
{
int a;
int arr[];
};
int main()
{
struct S s={0};//用malloc函数进行分配,正常不会这样使用
printf("%d", sizeof(s));//计算柔性数组的大小,是不包含柔性数组的,只计算它前面的变量
return 0;
}
正确的使用应该是这样的
struct S
{
int a;
int arr[];//大小未知,有的写成int arr[0]也是可以的
};
int main()
{
struct S* ptr = (struct S*)malloc(sizeof(struct S) + 10*sizeof(int));//10*sizeof(int)给数组的,后面的大小可以通过realloc进行改变
ptr->a = 10;
int i = 0;
for (i = 0; i < 10; i++)
{
ptr->arr[i] = i;
}
struct S* ps = (struct S*)realloc(ptr, sizeof(struct S) + 20 * sizeof(int));
if (ps != NULL)
{
ptr = ps;
}
printf("%d", ptr->arr);
free(ptr);
ptr = NULL;
return 0;
}
可能会有人认为将结构体中的数组改为指针也可以
struct s
{
int a;
int *arr;//在栈上开辟
};
int main()
{
struct s* ps = (struct s*)malloc(sizeof(struct s));
if (ps == NULL)//先对ps这个指针判断空指针
{
return 1;
}
ps->a = 10;
ps->arr = (struct s*)malloc(sizeof(10 * sizeof(int)));
if (ps->arr == NULL)//arr也是一个指针,所以也要判断是否是空针
{
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
{
ps->arr[i] = i;//达到和之前一样的效果
}
//增加
int*ptr = (int*)realloc(ps->arr, 20 * sizeof(int));
if (ptr != NULL)
{
ps->arr = ptr;
}
//使用
//释放,ps,和arr都是被malloc开辟出来,要先free指针空间,再free,ps的空间
free(ps->arr);
ps->arr = NULL;
free(ps);
ps = NULL;//但是这是有不足的地方,这不是柔性数组,进行了两次malloc同时就会对应两次free,malloc开辟次数越多,内存碎片也越多,内存利用率也就降低了,内存局部性原理,每次使用都是在他周边范围使用
return 0;
}
但实际上他malloc开辟了两次空间,留了过多的内存碎片,使得内存的利用率降低,
优势.方便开辟。方便释放