温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C语言中的柔性数组怎么使用

发布时间:2023-04-15 15:38:37 来源:亿速云 阅读:306 作者:iii 栏目:开发技术

这篇文章主要讲解了“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语言中的柔性数组怎么使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI