👦个人主页:@Weraphael
✍🏻作者简介:目前是C语言学习者
✈️专栏:C语言航路
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注
前言
说起数组,一维数组、二维数组、字符数组、整型数组和浮点型数组,我相信大家并不陌生吧,今天我们一起看看柔性数组!
目录
- 前言
- 一、柔性数组的概念和定义
- 二、柔性数组的特点
- 三、柔性数组的使用
- 四、柔性数组的优势
一、柔性数组的概念和定义
在C99中,结构中的最后一个元素允许是未知大小的数组,我们把这样的数组称为柔性数组成员。
【定义】
struct S
{int i;int a[]; //柔性数组
};
若有些编译器无法编译,可以改成以下这种:
struct S
{int i;int a[0];//柔性数组成员
};
二、柔性数组的特点
- 结构中的柔性数组前必须至少有一个其他成员
sizeof
返回的这种结构大小不包括柔性数组的内存
- 包含柔性数组成员的结构用
malloc
函数进行动态内存分配,并且分配的内存应该大于结构体大小,以适应柔性数组的预期大小
三、柔性数组的使用
动态内存开辟函数讲解:传送门
#include <stdio.h>
#include <stdlib.h>
struct S
{int i;char a[];
};
int main()
{//包含柔性数组成员的结构用`malloc`函数进行动态内存分配//并且分配的内存应该大于结构体大小struct S* sp = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(char));//若sp为空指针,说明开辟动态内存失败if (sp == NULL){return 1;}//否则开辟成功//使用sp->i = 100;for (int i = 0; i < 10; i++){sp->a[i] = 'x';}//打印for (int i = 0; i < 10; i++){printf("%c ", sp->a[i]);}//释放free(sp);sp = NULL;return 0;
}
甚至还能扩容
realloc
#include <stdio.h>
#include <stdlib.h>
struct S
{int i;char a[];
};
int main()
{//包含柔性数组成员的结构用`malloc`函数进行动态内存分配//并且分配的内存应该大于结构体大小struct S* sp = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(char));//若sp为空指针,说明开辟动态内存失败if (sp == NULL){return 1;}//否则开辟成功//使用sp->i = 100;for (int i = 0; i < 10; i++){sp->a[i] = 'x';}//扩容(多加10字节的空间)struct S* p = (struct S *)realloc(sp, sizeof(struct S) + sizeof(char) * 20);//如果p为空指针说明扩容失败if (p == NULL){return 1;}else{sp = p;p = NULL;}for (int i = 10; i < 20; i++){sp->a[i] = 'w';}//打印printf("%d\n", sp->i);for (int i = 0; i < 20; i++){printf("%c ", sp->a[i]);}return 0;
}
所以柔性数组在内存其实是这样的
它在内存是连续的
四、柔性数组的优势
除【柔性数组的使用】样例以外,也可以设计成下面这样:
#include <stdio.h>
#include <stdlib.h>struct S
{int i;char* a;
};int main()
{//为结构体开辟空间struct S* sp = (struct S*)malloc(sizeof(struct S));//若sp = NULL,说明开辟失败if (sp == NULL){return 1;}//否则开辟成功//使用内存空间sp->i = 100;//为char* a开辟10个字节空间sp->a = (char*)malloc(sizeof(char) * 10);//使用for (int i = 0; i < 10; i++){sp->a[i] = 'w';}//或者还能为char* a扩容char* p = (char*)realloc(sp->a, 20 * sizeof(char));if (p == NULL){return 1;}else{sp->a = p;p = NULL;}//使用扩容的空间for (int i = 10; i < 20; i++){sp->a[i] = 'J';}//打印printf("int i = %d\n", sp->i);for (int i = 0; i < 20; i++){printf("%c ", sp->a[i]);}//释放空间free(sp->a);sp->a = NULL;free(sp);sp = NULL;return 0;
}
一个常见的问题:为什么要先释放
sp->a
的内存空间
- 首先程序是先为结构体开辟空间
- 接着又为
char*
开辟空间
所以,若先对sp
释放空间,到后面就不能通过sp
找到char* c
开辟的空间
柔性数组好处的总结:
- 对于柔性数组来说,开辟空间(malloc)只需要一个,释放空间(free)也只需要一次,且内存空间是连续的,而对于上面的代码来说,开辟空间需要二次,释放空间也同样需要二次,且内存空间是不连续的。所以它第一个好处是方便内存释放
- 连续的内存有益于提高访问速度