这篇文章主要讲解了“C语言中的柔性数组怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言中的柔性数组怎么使用”吧!
1.什么是柔性数组
柔性数组就是大小可以变化的数组。
注意跟C99中的变长数组区分开来,变长数组指的是可以使用变量来指定大小,并且不能初始化的数组,比如:
int n = 0;scanf("%d", &n);int arr[n]; // 变长数组
柔性数组是在结构体中声明的。它满足:
是结构体的最后一个成员变量。
大小不确定,一般空出来或者用0来填充。
比如:
struct S{ char ch; double d; int arr[];};
或者:
struct S{ char ch; double d; int arr[0];};
上面的2中写法是等价的,但是有些编译器只支持其中的一种写法。
在进行如何使用的讲解之前,先来思考一个问题:结构体S的大小是多少?也就是说,sizeof(struct S)是多大?
不同的编译器结果不一定一样。事实上,sizeof(struct S)计算的是结构体中除了变长数组之外的大小,在VS2022,X64环境下,考虑内存对齐,计算出来的结果是16。
2.柔性数组应该如何使用
为了给柔性数组分配空间,应该使用动态内存管理。假设使用malloc来申请空间,我们应该考虑柔性数组的大小,算出总的大小。
以上面的struct S为例。假设我想要数组arr的大小是10个int,那么要开辟的总大小就是除了柔性数组之外的大小+柔性数组的大小。前面提到了,除了柔性数组之外的大小就是sizeof(struct S),而柔性数组的大小是10*sizeof(int),就能如下开辟空间:
struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));if (ps == NULL){ // ...}// ...
这样,结构体中的成员数组arr就有了10个int的空间了,我们可以正常的使用这个结构体,只需把成员数组arr当成int arr[10];这样的数组即可。
当然,之所以叫“柔性数组”,这个数组不仅可以指定初始化的大小,也可以改变大小,毕竟是动态内存开辟出来的。只需要使用realloc即可,新的大小的计算方式和前面一样,也是sizeof(struct S)+柔性数组新的大小。比如,如果我想把数组的大小扩大成原来的2倍,可以这么写:
struct S* tmp = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(int));if (tmp == NULL){ // ...}else{ ps = tmp;}// ...
这样,ps指向的结构体的最后一个成员数组的容量就变成了20个int。
记住,所有动态申请的内存,在使用结束后,都需要调用free释放。比如以上的结构体s使用完后,需要free(ps);。
3.柔性数组的替代方案及内存分布对比
其实,我们可以不使用柔性数组实现类似的效果。分析一下,以上的结构体struct S的特点是:
使用动态内存管理,在堆区上申请空间。
有一个成员数组,可以动态的改变大小。
如果不使用柔性数组,而是直接使用动态内存管理的思路,也是可以的。比如:
struct S{ char ch; double d; int* arr;};
先malloc出一个结构体出来。
struct S* ps = (struct S*)malloc(sizeof(struct S));if (ps == NULL){ // ...}// ...
接着再malloc出一块空间,交给arr管理。假设开辟出10个int的空间。
ps->arr = (int*)malloc(10 * sizeof(int));if (ps->arr == NULL){ // ...}// ...
如果想要扩容,直接对ps->arr进行realloc即可。比如,把arr指向的空间扩容成原来的2倍。
int* tmp = (int*)realloc(ps->arr, 20 * sizeof(int));if (tmp == NULL){ // ...}else{ ps->arr = tmp;}
这块空间使用结束后,记得释放空间。注意一定要先释放arr,再释放ps,因为如果先释放ps,结构体内的arr就成了野指针,就找不到原来arr指向的空间了,形成了内存泄漏。
free(ps->arr);ps->arr = NULL;free(ps);pf = NULL;
使用和不使用柔性数组的内存分布对比:
对于柔性数组,动态申请的内存只存放了一个完整的结构体,所有的成员变量(数组)整体上是连续的空间。
不使用柔性数组实现类似的效果,需要先动态开辟出一个结构体,再开辟出另外一块空间,用结构体的一个成员变量(一个指针)来管理。相当于malloc了2次,有2块独立的空间。
4.柔性数组有哪些优点
既然不使用柔性数组也能实现类似的效果,为什么还要使用柔性数组呢?因为柔性数组有以下的2个优点:
使用柔性数组只用malloc一次,free一次。如果不使用柔性数组,要malloc两次,free两次。在使用上,柔性数组更方便、更简单。
由于柔性数组在整体上只开辟了一块连续的空间,根据局部性原理,缓存的命中率更高,增加了效率(虽然其实也没增加多少)。
感谢各位的阅读,以上就是“C语言中的柔性数组怎么使用”的内容了,经过本文的学习后,相信大家对C语言中的柔性数组怎么使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!