关于那些柔性数组的知识

简介: 关于那些柔性数组的知识

一.什么是柔性数组

也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的。 在C99标准 中,结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。


🌝例子

//写法1
struct st_type
{
    int i ;
    int arr[];  //柔性数组成员
};
//写法2
struct st_type
{
    int i ;
    int arr[0]; //柔性数组成员
};
//对于写法2:有些编译器会报错无法编译
复制代码


二.柔性数组的特点

  • 🛸特点1  :结构中的柔性数组成员前面必须至少一个其他成员。
struct A
{
    int arr[];  //柔性数组成员
    int i;
};
//可能会报错,柔性数组成员前面必须至少一个其他成员
复制代码

  • 🚅特点2:  sizeof 返回的这种结构大小不包括柔性数组的内存。
struct A
{
    int i ; //4
    int arr[];
};
int main()
{
    printf("%d\n",sizeof(struct A)); //4
    return 0;
}
复制代码

  • 🚞特点3:  包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小
struct st_type
{
    int i ;
    int arr[];
};
int main()
{
    struct st_type* p = (struct st_type*)malloc(sizeof(struct st_type)+10*sizeof(int));
    //为数组arr开辟了10个整形大小的空间
    if( p!= NULL)
    {
        int i = 0;
        for(i = 0;i < 10;i++)
        {
            p->arr[i] = i;
            printf("%d ",p->arr[i]);
        }
        p->i = 100;
        printf("%d\n", p->i);
    }
    return 0;
}
复制代码

image.png

 

🎨为数组arr开辟了10个整形大小的空间


三.使用柔性数组的好处

🛍使用柔性数组的例子:

struct st_type
{
    int i;
    int arr[];  //柔性数组成员
};
int main()
{
    struct st_type* p = (struct st_type*)malloc(sizeof(struct st_type) + 10 * sizeof(int));
    //为数组arr开辟了10个整形大小的空间
    int i = 0;
    if (p != NULL)
    {
        for (i = 0; i < 10; i++)
        {
            //为柔性数组成员赋值
            p->arr[i] = i;
            printf("%d ", p->arr[i]);
        }
        p->i = 100;
        printf("%d\n", p->i);
    }
    else
    {
        printf("开辟失败\n");
        return -1;
    }
    //当空间不够时也可以增容
    struct st_type* ptr = (struct st_type*)realloc(p, sizeof(struct st_type) + 20 * sizeof(int));
    if (ptr == NULL)
    {
        printf("扩容失败\n");
        return -1;
    }
    else
    {
        p = ptr;  //把增容空间的地址赋给p
    }
    //使用
    for (i = 10; i < 20; i++)
    {
        p->arr[i] = i;
        printf("%d ", p->arr[i]);
    }
    //释放
    free(p);
    p = NULL;
    return 0;
}
复制代码


💎针对上面的,我们也可以使用动态数组实现

struct st_type
{
    int i ; 
    int* arr;//指向动态开辟的数组  
};
int main()
{
    struct st_type* ps = (struct st_type*)malloc(sizeof(struct st_type));
    ps-> i = 100;
    ps->arr = (int*)malloc(10*sizeof(int));
    int i = 0;
    for(i = 0;i <10;i++)
    {
        ps->arr[i] = i;
        printf("%d ",ps->arr[i]);
    }
    // a空间不够则增容
    int* ptr = (int*)realloc(ps->arr,20*sizeof(int));
    if(ptr == NULL)
    {
        printf("扩容失败\n");
        return -1;
    }
    else
    {
        ps->arr = ptr;
    }
    //使用
    for(i = 10;i<20;i++)
    {
        ps->arr[i] = i;
        printf("%d ",ps->arr[i]);
    }
    //释放!!注意释放顺序
    free(ps->arr);
    ps->arr = NULL;
    free(ps);
    ps = NULL;
    return 0;
}
复制代码


image.png

👒注意!!:要先释放结构体内动态开辟的数组,再释放动态开辟的结构体  


🤎对于上述的写法1和写法2可以实现相同的功能,但是写法1实现由两个好处

💦💨第一个好处:方便内存释放

如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。

💛第二个好处:有利于访问速度

连续的内存有益于提高访问速度,也有益于减少内存碎片。


四.什么是内存碎片

💓动态分配将不可避免会产生内存碎片的问题,那么什么是内存碎片?内存碎片即“碎片的内存”描述一个系统中所有不可用的空闲内存,这些碎片之所以不能被使用,是因为负责动态分配内存的分配算法使得这些空闲的内存无法使用,这一问题的发生,原因在于这些空闲内存以小且不连续方式出现在不同的位置。因此这个问题的或大或小取决于内存管理算法的实现上。                                                                                [摘自百度百科]

image.png

💢通俗来说,动态开辟空间是随机开辟的,空间之间的间隙就是内存碎片


相关文章
|
12天前
|
人工智能 自然语言处理 安全
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公是阿里云推出的一站式AI办公平台,主打"不止于对话,更注重交付",依托通义千问旗舰大模型,用户一句话即可完成数据分析、PPT生成、视频剪辑等复杂任务,直接输出可用成果。产品深度打通钉钉生态与企业OA,覆盖桌面端、网页端,提供企业标准版198元/人/月等多档订阅方案,新用户注册即赠2000积分,适配工程师、HR、财务等多职业办公场景,成为能动手干活的"全能AI同事"。
|
12天前
|
人工智能
千问办公官网入口:阿里AI办公QwenWork产品页和免费网页端链接
千问办公官网含两大入口:一是网页端(qwenwork.cn),即开即用,支持浏览器直接访问;二是阿里云产品页 https://t.aliyun.com/U/JNKJuO 提供免费/付费版详情、功能介绍及使用指南。
|
18天前
|
网络协议 Linux iOS开发
【2026实测】Wireshark下载+安装+汉化+使用教程(图文版,巨详细)
Wireshark 是一款免费开源的网络协议分析工具,可实时捕获、解析并可视化数据包,助你诊断网络故障、分析通信协议(如HTTP、DNS、TCP等)。支持Windows/macOS/Linux,含中文界面,新手入门便捷。(239字)
|
11天前
|
IDE 开发工具
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
Qoder国际版上线全新内置大模型Sonus(/ˈsoʊnəs/),全球领先,专精超长任务执行与电脑操作(Computer Use)。配合Qoder桌面端0.2.3版本,可自主完成编程、金融建模、科研及表格制作等复杂工作。现全面支持Qoder全系产品,效率提升3.2倍。
1303 8
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
|
13天前
|
缓存 人工智能 自然语言处理
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
本文是阿里云百炼平台Qwen3.8-Flash大模型的选型接入指南,作为兼顾性能与响应速度的高性价比多模态模型,它支持百万级上下文窗口、全场景多模态输入与完整智能体能力矩阵,适配编程辅助、智能体协作等核心场景。文中同步梳理了最新下调的阶梯定价、夜间4折等优惠活动,搭配OpenAI兼容流式调用示例,帮助开发者低成本快速落地高并发AI应用。
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
|
12天前
|
人工智能 API 内存技术
刚刚 DeepSeek V4.1 Flash 开启内测,1 分钟教你用上!
刚刚 DeepSeek 内测群发布了 DeepSeek V4.1 Flash 中间版本内测的消息,这次的模型采用了新的结构,原生支持多模态、能力更强、速度更快、且成本更低。
1976 15
|
17天前
|
人工智能 运维 BI
阿里云千问办公QwenWork深度解析:基于Qwen3.8,六大核心能力重构企业全自动化工作流与计费选型指南
传统AI办公工具大多停留在对话问答、文档摘要、简单文案生成层面,只能完成单点碎片化任务,无法自主拆解复杂业务流程,很难串联多工具、多文档、外部业务系统完成端到端完整工作交付。很多企业在落地AI办公的时候,需要组合多款不同工具,来回切换界面,手动复制粘贴中间结果,智能化改造落地门槛居高不下。千问办公QwenWork是整合多款智能体产品能力打造的一体化企业办公智能体平台,底层基座依托Qwen3.8大模型,打通桌面端Agent、云端Agent、企业协同Agent三种运行形态,不再局限简单问答,接收业务目标之后自主拆解任务步骤,调用各类工具,处理文档、表格、浏览器自动化、数据查询,直接输出可交付的办公
1681 4
|
18天前
|
缓存 数据可视化 开发工具
DeepSeek Harness 怎么更新?dsh 更新完整指南:更新本体(npx、npm、源码)与更新插件两种方式
DeepSeek Harness 的更新分两层:本体更新(npx 自动最新、npm update -g、源码 git pull)与插件更新(插件市场点更新、命令行覆盖安装)。本文按「准备 → 更新本体 → 更新插件 → 更新后检查」四步走,覆盖新手常见疑问。
2016 1
DeepSeek Harness 怎么更新?dsh 更新完整指南:更新本体(npx、npm、源码)与更新插件两种方式
|
13天前
|
缓存 JSON API
阿里云千问Qwen3.8‑Max深度解析:核心能力、订阅计费规则、API接入配置与生产落地完整教程
Qwen3.8‑Max作为千问系列新一代MoE架构旗舰基座,总参数量达到2.4万亿,激活参数950亿,是面向复杂专业任务、长周期智能体、工程级代码开发、多模态深度解析的高阶大模型,原生支持文本、图像、视频多模态输入,最大上下文窗口达到百万Token,最大输出Token支持131072,内置深度思考推理链路,在编程、科研、法律金融专业分析、长视频文档解析、自主Agent任务等场景能力表现突出。很多开发者在项目前期直接接入该旗舰模型,却对模型能力边界、多种计费模式、订阅套餐权益、API参数配置、上下文缓存优化缺乏完整认知,出现成本失控、接口报错、长文本信息丢失、深度思考模式额外消耗大量Token等
878 3
|
6天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)

热门文章

最新文章