c99标准中,结构体类型的最后一个元素允许是未知大小的数,叫做『柔性数组』成员
柔性数组的大小可变
struct S
{
int n;
char c;
int a[0];//柔性数组成员
};
有些编译器会报错无法编译,也可以改成:
struct
{
int n;
char c;
int a[];//柔性数组成员
};
所以 以下两种柔性数组的写法是一样的
int a[] //柔性数组
int a[0]//柔性数组
柔性数组的特点:
1 结构体中的柔性数组成员的前面必须至少有一名其他成员
2 sizeof计算结构体大小时,不包括柔性数组的所占的内存大小
3 包含柔性数组成员的结构体需要使用malloc函数进行内存的动态分配,且分配的内存应该大于结构体的大小,以适应柔性数组的预期大小
使用:
包含柔性数组的结构体类型设计:
struct S
{
int n;
char c;
int arr[];
};
让arr数组的大小变为5,存储1~5
#include<stdio.h>
#include<string.h>
#include<errno.h>
struct S
{
int n;
char c;
int arr[];
};//结构体大小为8
int main()
{ // 8 + 20
struct S* ps = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int));
if (ps == NULL)//malloc动态开辟空间失败
{
printf("%s\n", strerror(errno));//打印错误信息
return 1;
}
//使用
ps->n = 100;
ps->c = 'a';
int i = 0;
for (i = 0; i < 5; i++)
{
ps->arr[i] = i + 1;
printf("%d ", ps->arr[i]);
}
//释放
free(ps);
ps = NULL;
return 0;
}
让arr数组的大小变成10,存储1~10
使用realloc调整malloc动态开辟的空间
#include<stdio.h>
#include<string.h>
#include<errno.h>
struct S
{
int n;
char c;
int arr[];
};//结构体大小为8
int main()
{ // 8 + 20
struct S* ps = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int));
if (ps == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
//调整 8 + 40
struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 10 * sizeof(int));
if (ptr == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
else
{
ps = ptr;
//使用
ps->n = 100;
ps->c = 'a';
int i = 0;
for (i = 0; i < 10; i++)
{
ps->arr[i] = i + 1;
printf("%d ", ps->arr[i]);
}
}
//释放
free(ps);
ps = NULL;
return 0;
}
柔性数组的优势:
若不使用柔性数组,以上结构体类型的设计也可以写成:
struct S
{
int n;
char c;
int *arr;//指向一块动态开辟的空间
};
使用:
#include<stdio.h>
#include<string.h>
#include<errno.h>
struct S
{
int n;
char c;
int *arr;//指向一块动态开辟的空间
};
int main()
{
struct S* ps = (struct S*)malloc(sizeof(struct S));
if (ps == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
int* str = (int*)malloc(5 * sizeof(int));
if (str == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
ps->arr = str;
//使用
ps->n = 100;
ps->c = 'a';
int i = 0;
for (i = 0; i < 5; i++)
{
ps->arr[i] = i + 1;
printf("%d ", ps->arr[i]);
}
//扩容
int* ptr = (int*)realloc(ps->arr, 10 * sizeof(int));
if (ptr == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
ps->arr = ptr;
//使用
for (i = 5; i < 10; i++)
{
ps->arr[i] = i + 1;
printf("%d ", ps->arr[i]);
}
//释放
free(ps->arr);
ps->arr = NULL;
free(ps);
ps = NULL;
return 0;
}
包含柔性数组的结构体动态开辟空间:连续的一块空间
malloc动态开辟空间1次,free1次 容易维护,不易出错
连续的内存有益于提高访问速度,也有益于减少内存碎片,内存使用率较高
不包含柔性数组的结构体动态开辟空间:不连续的空间
malloc动态开辟空间2次,free两次 不易维护,容易出错
不连续的内存,使得内存碎片较多,内存使用率较低