柔性数组
柔性数组,简而言之就是一个在struct结构里的标识占位符(不占结构struct的空间),只能在堆上生成。
在结构体内,有一个数组,必须是结构体中的最后一个元素,而且有特定的形式[]或者[0],结构体中至少要有两个成员体变量。
实例:
此时的字符数组 name 是不占空间的。
柔性数组的应用实例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct data
{
int len; //一般用来表示字符数组的字符个数
char name[];
}S;
int main(void)
{
S s;
printf(“sizeof(s)=%d\n”,sizeof(s));
<span class="hljs-keyword">int</span> len = <span class="hljs-number">10</span>; <span class="hljs-comment">//申请空间 </span>
<span class="hljs-keyword">struct</span> data *p =(<span class="hljs-keyword">struct</span> data*)<span class="hljs-built_in">malloc</span>(<span class="hljs-keyword">sizeof</span>(s)+<span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">char</span>)*len);
<span class="hljs-comment">//判断是否申请成功&请空处理 </span>
p->len = len;
<span class="hljs-built_in">strcpy</span>(p->name,<span class="hljs-string">"helloqpy"</span>);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>,p->name);
<span class="hljs-comment">//释放指针p</span>
<span class="hljs-built_in">free</span>(p);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
程序运行结果:
这样子我们就有疑问,柔性数组到底方便在哪里了?每次使用它还要申请堆内存,我们直接在结构体里面放一个字符串指针,然后给这个指针再malloc分配一下内存不就好了么?
如下面代码:
但是注意:此时的len和字符串指针是一块存储的 但是结构体里面的字符串 也就是helloqpy和我们的结构体是分开的 ,其存储的位置在指针存储。
那么我们为什么要使用柔性数组??
是因为我们想给一个结构体内的数据分配一个连续的内存!这样做的意义有两个好处:
第一个意义是,方便内存释放。如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。(读到这里,你一定会觉得C++的封闭中的析构函数会让这事容易和干净很多)
第二个原因是,这样有利于访问速度。连续的内存有益于提高访问速度,也有益于减少内存碎片。(其实,我个人觉得也没多高了,反正你跑不了要用做偏移量的加法来寻址)
使用柔性数组实现斐波那契数列
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct data
{
int n; //表示数列的项数
int arr[];//柔性数组
}S;
//遍历斐波那契数列的函数
void show_arr(struct data *p_str)
{
int i=0;
for(i=0;i<p_str->n;i++)
//注意此处是p_str->n,而不是len 要看传进来的参数
{
printf(“第(%d)项arr[%d]=%d\n”,(i+1),i,p_str->arr[i]);
}
}
//生成斐波那契数列的函数
void create_arr(int len)
{
struct data *p_str = (struct data *)malloc(sizeof(struct data)+sizeof(int)*len);
p_str->n = len;
//循环赋值
int i = 0;
for(i=0;i<len;i++)
{
if(i<=1) //arr[0]和arr[1]是第一项和第二项是1
p_str->arr[i] =1;
else if(i>=2)
{
//后面的是前两项的和
p_str->arr[i] = p_str->arr[i-1] + p_str->arr[i-2];
}
}
//调用遍历函数
show_arr(p_str);
free(p_str);
}
int main(void)
{
int len = 10;
//调用生成数列的函数即可
create_arr(len);
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
函数实现效果如下:
</article>