在学习之前,我们首先要了解柔性数组是放在结构体当中的,知道这一点,我们就开始今天的学习吧!
1.柔性数组的声明
在C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员
这里的结构是结构体
我们看个代码了解:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> //柔性数组的声明 typedef struct S { int n; char c; char arr[0];//它就是柔性数组 //还有另一种写法,就是char arr[],这两种写法在我们vs中都是不会出错的 }S; int main() { //printf("%zd\n", sizeof(S)); return 0; }
2.柔性数组的特点
1.结构中的柔性数组成员前面必须至少有一个其他成员
2.sizeof返回的这种结果大小不包括柔性数组的内存
3.包含柔性数组成员的结构用malloc函数进行内存的动态分配,并且分配的内存应该大于结构体的大小,以适应柔性数组的预期大小
我们可以验证一下:
我们求一下这个结构体的大小:
typedef struct S { int n; char arr[];//它就是柔性数组 }S; int main() { printf("%zd\n", sizeof(S)); return 0; }
运行一下,我们发现它求出来结构体的大小是前面整型的大小,没有包含这个柔性数组的大小
我们再看一个代码来了解柔性数组的整体特性
typedef struct S { int n; char arr[];//它就是柔性数组 }S; int main() { //未使用这个柔性数组前,计算一下这个结构体的总大小,和后面使用之后作比较 //看看有什么不同 printf("%d\n", sizeof(S)); //我们为这个结构体成员和柔性数组成员分配动态内存空间 S* pc = (S*)malloc(sizeof(char) * 10 + sizeof(S)); if (pc == NULL) { perror("malloc"); return 1; } //开始使用柔性数组 pc->n = 100; int i = 1; for (i = 1; i <= 10; i++) { pc->arr[i] = i; printf("%d ", pc->arr[i]); } //如果空间不足,我们可以进行增容 S* str = (S*)realloc(pc,sizeof(S) + sizeof(sizeof(char) * 20)); if (str == NULL) { printf("%s\n", strerror(errno)); return 1; } pc = str; printf("\n"); //在这里我们可以求一下现在结构体的大小,看它在使用了柔性数组之后 //结构体的总大小是否发生了变化 printf("%d\n", sizeof(S)); //释放空间 free(pc); pc = NULL; return 0; }
我们运行查看一下结果
我们发现
1.结构体使用柔性数组前后,结构体总大小没有发生变化,都是4
2.我们使用别的办法也可以达到柔性数组所达到的效果,为什么还要存在柔性数组呢?
这就引出了我们下一个知识点,为什么存在柔性数组
3.为什么存在柔性数组
我们用别的办法实现一下这个柔性数组所实现的功能,对比着来看更能理解
typedef struct S { int n; char* arr; }S; int main() { printf("未动态开辟时内存大小:%zd\n", sizeof(S)); //为整个结构体分配动态内存空间 S* pc = (S*)malloc(sizeof(S)); if (pc == NULL) { perror("malloc"); return 1; } //使用这块空间 pc->n = 100; //再用malloc为指针arr分配空间 pc->arr = (char*)malloc(sizeof(char) * 10); if (pc->arr == NULL) { perror("malloc"); return 1; } //使用给arr分配的这块空间 int i = 0; for (i =0; i < 10; i++) { pc->arr[i] = 'Q'; printf("%c ", pc->arr[i]); } printf("\n"); printf("malloc这块空间后内存大小:%zd\n", sizeof(S)); //对这块空间进行增容 char* ptr = (char*)realloc(pc->arr, sizeof(char) * 20); if (ptr == NULL) { perror("realloc"); return 1; } //使用增容后的空间 ptr = pc->arr; for (i = 0; i < 10; i++) { pc->arr[i] = 'L'; printf("%c ",pc->arr[i]); } printf("\n"); printf("realloc这块空间后内存大小:%zd\n", sizeof(S)); //释放空间 free(pc->arr); pc->arr = NULL; free(pc); pc = NULL; return 0; }
我们比较一下两种写法,它们可以达到一样的效果
但是
柔性数组:
1.malloc只需要开辟一次
2.free空间一次
3.开辟的空间是连续的
普通写法:
1.malloc两次
2.free两次
3.开辟的空间不一定连续
我们要知道malloc的次数越多,越容易处处,可能free顺序不对或者忘记free,造成内存泄漏;同时,内存碎片越多,没别利用的空间就越多,造成空间的浪费。
此时,我们就要知道存在即合理,柔性数组的存在是有一定的道理的。
接下来我们总结一下柔性数组的好处
4.柔性数组的好处
1.方便内存释放(我们在为什么存在柔性数组里已经分析过了)
2.有利于提高访问效率
连续的内存有益于提高访问速度,也有益于减少内存碎片
好了,这就是关于柔性数组的全部知识,大家要慢慢感悟,咱们下期再见!!!