柔性数组
也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的。C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。
示例:
struct S {
int n;
int arr[0];//未知大小的-柔性数组成员-数组的大小是可以调整的
//int arr[];//也可以这么写
};
int main() {
struct S* ps = (struct S*)malloc(sizeof(int) + 5 * sizeof(int));
ps->n = 100;
for (int i = 0; i < 5; i++) {
ps->arr[i] = i;
}
//假设此处内存不够用,我们想要扩容
struct S* ptr = (struct S*)realloc(ps, 100);
if (ptr != NULL) {
ps = ptr;
}
for (int j = 5; j < 10; j++) {
ps->arr[j] = j;
}
free(ps);
ps = NULL;
return 0;
}
使用:
struct S* ps = (struct S*)malloc(sizeof(struct S));
结构体指针ps维护一块动态开辟的结构体内存空间
开辟的结构体内存空间存放int n(4字节)和int *arr(4字节),arr是一个指针指向一个地址
ps->arr = (int*)malloc(5 * sizeof(int));
在arr指向的地址上再动态开辟一块内存空间,用arr维护,arr指向的这块空间可以由我们自己设定
代码:
struct S {
int n;
int* arr;
};
int main() {
struct S* ps = (struct S*)malloc(sizeof(struct S));//结构体指针ps维护一块动态开辟的结构体内存空间
//开辟的结构体内存空间存放int n和int *arr,arr是一个指针指向一块空间
ps->arr = (int*)malloc(5 * sizeof(int));//在arr指向的地址上再动态开辟一块内存空间,用arr维护
for (int i = 0; i < sizeof(ps->arr) / sizeof(ps->arr[0]); i++) {
ps->arr[i] = i;
}
//扩容
int* ptr = (int*)realloc(ps, 10 * sizeof(int));
if (ptr != NULL) {
ps->arr = ptr;
}
for (int i = 5; i < sizeof(ps->arr)/sizeof(ps->arr[0]); i++) {
ps->arr[i] = i;
//这里动态开辟一块连续存储5个字节的的内存空间--类似于数组,arr维护这块空间,相当于数组首元素地址,故可以用arr[i]方式访问
}
free(ps->arr);
free(ps);
ps = NULL;
return 0;
}
柔性数组的特点:
·结构中的柔性数组成员前面必须至少一个其他成员。
sizeof返回的这种结构大小不包括柔性数组的内存。
·包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
柔性数组的好处
第一个好处是:方便内存释放
如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。
第二个好处是:这样有利于访问速度.
连续的内存有益于提高访问速度,也有益于减少内存碎片。(其实,我个人觉得也没多高了,反正你跑不了要用做偏移量的加法来寻址)
扩展阅读:
C语言结构体里的数组和指针