IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【适合蹲马桶时观看】你有没有听说过柔性数组? -> 正文阅读

[C++知识库]【适合蹲马桶时观看】你有没有听说过柔性数组?

📌 本文作者: Foxny

📃 更新记录: 2021.8.14

? 勘误记录: 无

💬 参考文献: 百度百科、比特科技

📜 本文声明: 由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!


一、柔性数组介绍

📚 定义:柔性数组(Flexible Array),又称可变长数组。一般数组的长度是在编译时确定,而柔性数组对象的长度在运行时确定。在定义结构体时允许你创建一个空数组(例如:arr [ 0 ]? ),该数组的大小可在程序运行过程中按照你的需求变动。

🔍 出处:柔性数组(Flexible Array),是在C语言的 C99 标准中,引入的新特性。结构中的最后一个元素的大小允许是未知的数组,即为柔性数组。

【百度百科】在 ANSI 的标准确立后,C语言的规范在一段时间内没有大的变动,然而C++在自己的标准化创建过程中继续发展壮大。《标准修正案一》在1994年为C语言创建了一个新标准,但是只修正了一些C89标准中的细节和增加更多更广的国际字符集支持。不过,这个标准引出了1999年ISO 9899:1999的发表。被称为C99,C99被ANSI于2000年3月采用。

💬 演示:

struct S {
    int n;
    int arr[]; // 👈 柔性数组成员
};

??? 部分编译器可能会报错,可以试着将 a [ 0 ] 改为 a [ ]

struct S {
    int n;
    int arr[]; // 👈 柔性数组成员
};

二、柔性数组的特点

💬 结构中的柔性数组成员的前面必须至少有一个其他成员:

typedef struct st_type {
    int i;    // 👈 必须至少有一个其他成员
    int a[0]; // 👈 柔性数组成员
} type_a;

💬 sizeof 计算这种结构的大小是不包含柔性数组成员的:

#include <stdio.h>

struct S {
    int n; // 4
    int arr[]; // 大小是未知的
};

int main() {
    struct S s = {0};
    printf("%d\n", sizeof(s));

    return 0;
}

🚩? 4

💬 包含柔性数组成员的结构,用 malloc 函数进行内存分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小:

#include <stdio.h>
#include <stdlib.h>

struct S {
    int n;
    int arr[0];
};

int main() {
    // 期望arr的大小是10个整型

    //         给n的            给arr[]的
    //           👇                👇
    struct S* ps = (struct S*)malloc(sizeof(struct S) + sizeof(int)); 
    // 后面+的大小就是给柔性数组准备的

    return 0;
}

💡 分析:

?

三、柔性数组的使用

💬 代码演示:

#include <stdio.h>
#include <stdlib.h>

struct S {
    int n;
    int arr[0];
};

int main() {
    // 期望arr的大小是10个整型
    struct S* ps = (struct S*)malloc(sizeof(struct S) + sizeof(int));
    ps->n = 10;

    // 使用
    int i = 0;
    for (i = 0; i < 10; i++) {
        ps->arr[i];
    }

    // 增容
    struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 20*sizeof(int));
    if (ptr != NULL) {
        ps = ptr;
    }

    // 再次使用 (略)

    // 释放
    free(ps);
    ps = NULL;

    return 0;
}

🐞 查看地址:

四、柔性数组的优势

💬 代码1:使用柔性数组

/* 代码1 */
#include <stdio.h>
#include <stdlib.h>

struct S {
    int n;
    int arr[0];
};

int main() {
    // 期望arr的大小是10个整型
    struct S* ps = (struct S*)malloc(sizeof(struct S) + sizeof(int));
    ps->n = 10;

    // 使用
    int i = 0;
    for (i = 0; i < 10; i++) {
        ps->arr[i];
    }

    // 增容
    struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 20*sizeof(int));
    if (ptr != NULL) {
        ps = ptr;
    }

    // 再次使用 (略)

    // 释放
    free(ps);
    ps = NULL;

    return 0;
}

💬 代码2:直接使用指针

想让n拥有自己的空间,其实不使用柔性数组也可以实现。

/* 代码2 */

#include <stdio.h>
#include <stdlib.h>

struct S {
    int n;
    int* arr;
};

int main() {
    struct S* ps = (struct S*)malloc(sizeof(struct S));
    if (ps == NULL)
        return 1;
    ps->n = 10;
    ps->arr = (int*)malloc(10 * sizeof(int));
    if (ps->arr == NULL)
        return 1;

    // 使用
    int i = 0;
    for (i = 0; i < 10; i++) {
        ps->arr[i];
    }

    // 增容
    int* ptr = (struct S*)realloc(ps->arr, 20 * sizeof(int));
    if (ptr != NULL) {
        ps->arr = ptr;
    }

    // 再次使用 (略)

    // 释放
    free(ps->arr); // 先free第二块空间
    ps->arr = NULL;
    free(ps);
    ps = NULL;

    return 0;
}

? 上面的 代码1代码2 可以完成同样的同能,哪个更好呢?

💡 显而易见, 代码1 更好:

????? ① 第一个好处:有利于内存释放

虽然 代码2 实现了相应的功能,但是和 代码1 比还是有很多不足之处的。代码2 使用指针完成,进行了两次 malloc ,而两次 malloc 对应了两次 free ,相比于 代码1 更容易出错如果我们的代码是在一个给别人用的函数中,你在里面做了两次内存分配,并把整个结构体返回给用户。虽然用户调用 free 可以释放结构体,但是用户并不知道这个结构体内的成员也需要 free,所以你不能指望用户来发现这件事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好(而不是多次分配),并且返回给用户一个结构体指针,用户只需使用一次 free 就可以把所有的内存都给释放掉,可以间接地减少内存泄露的可能性。

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

连续内存多多少少有益于提高访问速度,还能减少内存碎片。malloc 的次数越多,产生的内存碎片就越多,这些内存碎片不大不小,再次被利用的可能性很低。内存碎片越多,内存的利用率就会降低。频繁的开辟空间效率会变低,碎片也会增加。

?🔺 总结:因此,使用柔性数组,多多少少是有好处的。

?

?

?


本章完

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-15 15:19:21  更:2021-08-15 15:19:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 7:01:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码