• 柔性数组详解


    目录

    导读:

    1. 什么是柔性数组

    2. 柔性数组的特点

    3. 柔性数组的使用 

    4. 柔性数组与其它对比优势

    5. 内存碎片 


    导读:

    有关柔性数组开辟相关的malloc函数博文:

    C语言动态内存管理(malloc, calloc,realloc)详解-CSDN博客

    结构体以及其大小的计算:

    结构体、枚举以及联合类型在内存中的存储与大小计算-CSDN博客

    1. 什么是柔性数组

    柔性数组也称为变长数组,是一种动态数组的实现方式。

    与普通数组不同的是,柔性数组在定义时不需要明确指定数组大小,在程序运行时可以动态地分配和扩展数组大小。

    柔性数组是通过C99标准中提供的“结构体成员为未知长度的数组”的特性来实现的,它需要一个结构体来作为数组的容器,并且在结构体定义中,最后一个数组成员不指定长度,例如:

    1. struct S
    2. {
    3. char c;
    4. int i;
    5. int arr[0];//未知大小的数组 - 柔性数组成员
    6. };

    同一种写法:

    上面的一种写法有的编译器会报错

    1. struct S
    2. {
    3. char c;
    4. int i;
    5. int arr[];//未知大小的数组 - 柔性数组成员
    6. };

    2. 柔性数组的特点

    • 结构中的柔性数组成员前面必须至少一个其他成员。
    • sizeof 返回的这种结构大小不包括柔性数组的内存。
    • 包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大 小,以适应柔性数组的预期大小。

    例如我们把上诉结构体的大小计算一下

    1. struct S
    2. {
    3. char c;
    4. int i;
    5. int arr[];//未知大小的数组 - 柔性数组成员
    6. };
    7. int main()
    8. {
    9. printf("%d\n", sizeof(struct S));
    10. return 0;
    11. }

    运行结果:

    3. 柔性数组的使用 

    使用柔性数组时,我们需要手动分配内存空间,并且调整数组的大小。例如,可以使用malloc函数分配内存空间,并根据实际需要调整数组的大小:

    1. struct S
    2. {
    3. char c;
    4. int i;
    5. int arr[];//未知大小的数组 - 柔性数组成员
    6. };
    7. int main()
    8. {
    9. struct S* ps = (struct S*)malloc(sizeof(struct S) + 20);
    10. if (ps == NULL)
    11. {
    12. perror("malloc");
    13. return 1;
    14. }
    15. int i = 0;
    16. ps->i = 100;
    17. for (i = 0; i < 100; i++)
    18. {
    19. ps->arr[i] = i;
    20. }
    21. for (i = 0; i < 100; i++)
    22. {
    23. printf("%d ", ps->arr[i]);
    24. }
    25. free(ps);
    26. ps = NULL;
    27. return 0;
    28. }

    运行结果:

    4. 柔性数组与其它对比优势

    我们来看下面两段代码,其设计是一样的

    1. struct S
    2. {
    3. char c;
    4. int i;
    5. int* data;
    6. };
    7. int main()
    8. {
    9. struct S* ps = (struct S*)malloc(sizeof(struct S));
    10. if (ps == NULL)
    11. {
    12. perror("malloc1");
    13. return 1;
    14. }
    15. ps->c = 'w';
    16. ps->i = 100;
    17. ps->data = (int*)malloc(20);
    18. if (ps->data == NULL)
    19. {
    20. perror("malloc2");
    21. return 1;
    22. }
    23. int i = 0;
    24. for (i = 0; i < 5; i++)
    25. {
    26. ps->data[i] = i;
    27. }
    28. for (i = 0; i < 5; i++)
    29. {
    30. printf("%d ", ps->data[i]);
    31. }
    32. //空间不够了,增容
    33. int* ptr = (int*)realloc(ps->data, 40);
    34. if (ptr == NULL)
    35. {
    36. perror("realloc");
    37. return 1;
    38. }
    39. else
    40. {
    41. ps->data = ptr;
    42. }
    43. //增容成功就使用
    44. //...
    45. //释放
    46. free(ps->data);
    47. ps->data = NULL;
    48. free(ps);
    49. ps = NULL;
    50. return 0;
    51. }

    我们在使用malloc给柔性数组开辟内存时,使用完后是需要释放内存的,我们来看它们在内存中的存放

    这种开辟的内存空间并不是紧挨着后面开的,而是随便找的一块内存空间,这就导致我们需要多次释放内存。

    而柔性数组是紧挨着结构体后开辟的空间,可以直接一次性的释放

    1. struct S
    2. {
    3. char c;//1
    4. //3
    5. int i;//4
    6. int arr[];//未知大小的数组 - 柔性数组成员
    7. };
    8. int main()
    9. {
    10. struct S* ps = (struct S*)malloc(sizeof(struct S) + 20);
    11. if (ps == NULL)
    12. {
    13. perror("malloc");
    14. return 1;
    15. }
    16. ps->c = 'w';
    17. ps->i = 100;
    18. int i = 0;
    19. for (i = 0; i < 5; i++)
    20. {
    21. ps->arr[i] = i;
    22. }
    23. //打印
    24. for (i = 0; i < 5; i++)
    25. {
    26. printf("%d ", ps->arr[i]);
    27. }
    28. //空间不够了
    29. struct S* ptr = (struct S*)realloc(ps, sizeof(struct S)+40);
    30. if (ptr != NULL)
    31. {
    32. ps = ptr;
    33. }
    34. else
    35. {
    36. perror("realloc");
    37. return 1;
    38. }
    39. //增容成功后,继续使用
    40. //释放
    41. free(ps);
    42. ps = NULL;
    43. return 0;
    44. }

     

    5. 内存碎片 

    因为有时内存的开辟不是紧挨着的,而是一块一块的,这就造成了一些内存的浪费,所以有时像柔性数组这样紧挨着开辟的是很有必要的。

  • 相关阅读:
    第一套列表卷子
    外包干了3个月,技术倒退2年。。。
    【木板】Python实现-附ChatGPT解析
    玩转Linux与运维岗(31)
    【Dubbo3高级特性】「框架与服务」服务并发控制及集群负载均衡的实践指南(含扩展SPI)
    迁徙数据平台简单介绍
    【机器学习】LoRA:大语言模型中低秩自适应分析
    解除百度文库VIP、语雀、知乎付费限制,原来这么简单
    深入理解计算机网络-4信号编码与调制4
    解决java.io.IOException: Network error
  • 原文地址:https://blog.csdn.net/qq_64818885/article/details/133419749