• C语言之动态内存管理_柔性数组篇(2)


    目录

    柔性数组的特点

    柔性数组的使用 

    动态内存函数增容柔性数组模拟实现 

    柔性数组的优势


    今天接着来讲解一下柔性数组知识。

    柔性数组的特点

    C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做【柔性数组】成员。

    • 结构体中
    • 最后一个成员
    • 未知大小的数组【柔性数组】
    1. struct Stu
    2. {
    3. char c;
    4. int i;
    5. int arr[];
    6. //也可以这样写int arr[0]
    7. //未知大小的数组 -柔性数组成员
    8. };
    • 结构中的柔性数组成员前面必须至少一个其他成员。
    • sizeof 返回的这种结构大小不包括柔性数组的内存。
    • 包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。 

    我们来验证一下 【sizeof 返回的这种结构大小不包括柔性数组的内存。】--->【验证成功】


    1. #include
    2. struct Stu
    3. {
    4. char c;//1
    5. int i;//4
    6. //对齐规则:8
    7. int arr[];
    8. //也可以这样写int arr[0]
    9. //未知大小的数组 -柔性数组成员
    10. };
    11. int main()
    12. {
    13. printf("%d", sizeof(struct Stu));
    14. return 0;
    15. }

     

     验证完之后,我们再来学习一下【动态内存函数在柔性数组上的应用】吧! 


    1. #include
    2. struct Stu
    3. {
    4. char c;//1
    5. int i;//4
    6. //对齐规则:8
    7. int arr[];
    8. //也可以这样写int arr[0]
    9. //未知大小的数组 -柔性数组成员
    10. };
    11. int main()
    12. {
    13. struct Stu* p = (struct Stu*)malloc(sizeof(struct Stu)+20);//arr里放5个整型
    14. if (p == NULL)
    15. {
    16. perror("malloc");
    17. return 1;
    18. }
    19. free(p);
    20. p = NULL;
    21. return 0;
    22. }

    1. #include
    2. struct Stu
    3. {
    4. char c;//1
    5. int i;//4
    6. //对齐规则:8
    7. int arr[];
    8. //也可以这样写int arr[0]
    9. //未知大小的数组 -柔性数组成员
    10. };
    11. int main()
    12. {
    13. struct Stu* p = (struct Stu*)malloc(sizeof(struct Stu)+20);//arr里放5个整型
    14. if (p == NULL)
    15. {
    16. perror("malloc");
    17. return 1;
    18. }
    19. //发10个整型
    20. struct Stu* s = (struct Stu*)realloc(p, sizeof(struct Stu) + 40);
    21. if (s != NULL)
    22. {
    23. p = s;
    24. }
    25. else
    26. {
    27. perror("realloc");
    28. return 1;
    29. }
    30. //释放
    31. free(p);
    32. p = NULL;
    33. return 0;
    34. }

     想必大家都知道为什么叫柔性数组,因为【利用realloc任意调整数组的空间大小】记得及时释放

     柔性数组需要对齐吗?动动小手测试一下。需要40 

    柔性数组的使用 

    对柔性数组赋值1,2,3,4,5并打印出来。

    1. #include
    2. #include
    3. struct Stu
    4. {
    5. char c;//1
    6. int i;//4
    7. //对齐规则:8
    8. int arr[];
    9. //也可以这样写int arr[0]
    10. //未知大小的数组 -柔性数组成员
    11. };
    12. int main()
    13. {
    14. struct Stu* p = (struct Stu*)malloc(sizeof(struct Stu)+20);//arr里放5个整型
    15. if (p == NULL)
    16. {
    17. perror("malloc");
    18. return 1;
    19. }
    20. p->c = 't';
    21. p->i = 7;
    22. int i = 0;
    23. for (i = 0;i < 5; i++)
    24. {
    25. p->arr[i] = i+1;
    26. }
    27. for (i = 0; i < 5; i++)
    28. {
    29. printf("%d ", p->arr[i]);
    30. }
    31. //放10个整型
    32. struct Stu* s = (struct Stu*)realloc(p, sizeof(struct Stu) + 40);
    33. if (s != NULL)
    34. {
    35. p = s;
    36. }
    37. else
    38. {
    39. perror("realloc");
    40. return 1;
    41. }
    42. //释放
    43. free(p);
    44. p = NULL;
    45. return 0;
    46. }

    柔性数组还可以应用于【通讯录 】,后期我们也会去实现通讯录,并用【柔性数组】优化。

    动态内存函数增容柔性数组模拟实现 

    • 需要释放两次和开辟两次空间
    • 频繁的不连续开辟,内存碎片很多,内存的利用率很低
    1. #include
    2. #include
    3. struct S
    4. {
    5. char c;
    6. int i;
    7. int* a;
    8. };
    9. int main()
    10. {
    11. //为结构体开辟空间
    12. struct S* ps = (struct S*)malloc(sizeof(struct S));
    13. if (ps == NULL)
    14. {
    15. perror("malloc");
    16. return 1;
    17. }
    18. ps->c = 'T';
    19. ps->i = 7;
    20. ps->a = (int*)malloc(20);
    21. if ( ps->a == NULL)//注意写法ps->a
    22. {
    23. perror("malloc");
    24. return 1;
    25. }
    26. //使用
    27. int i = 0;
    28. for (i = 0; i < 5; i++)
    29. {
    30. ps->a[i] = i + 1;
    31. }
    32. for (i = 0; i < 5; i++)
    33. {
    34. printf("%d ", ps->a[i]);
    35. }
    36. //不够继续增加容
    37. int* pd = (int*)realloc(ps->a, 40);
    38. if (pd != NULL)
    39. {
    40. ps->a = pd;
    41. }
    42. else
    43. {
    44. perror("realloc");
    45. return 1;
    46. }
    47. printf("\n");
    48. //再次赋值
    49. int j = 0;
    50. for (j = 0; j < 10; j++)
    51. {
    52. ps->a[j] = j + 1;
    53. }
    54. for (j = 0; j < 10; j++)
    55. {
    56. printf("%d ", ps->a[j]);
    57. }
    58. //释放
    59. free(ps->a);
    60. ps->a = NULL;
    61. }

     

    柔性数组的优势

     通过上面两端代码【柔性数组】和【指针】的比较,即便它们的功能一致,我们可以清晰的发现【柔性数组的优势】。

    【优点1】方便释放 一次性就释放完全


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

    【优点2】这样有利于访问的速度,减少内存碎片,提高空间利用率


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

    最后,有一篇文章,感谢他让我受益匪浅。 

    C语言结构体里的成员数组和指针 | 酷 壳 - CoolShell

    【建议书】C陷阱与缺陷  高质量C\C++ 剑指offer 明解C语言等等 

    最后我想对我自己说,其实学习就是这样,刚开始并不喜欢计算机这门专业。其实我很想去选小语种西班牙语去到国外做翻译去看世界,而且我的理科思维并不好,但是在选择这门学科之后,当我开始认真的学习一些C语言的语法之后,我看到我自己独立写出来的游戏小程序的时候,还是挺有成就感,特别看到博客被大家看到,传递一些知识,还是很幸福的。写博客挺费时间的,但是我希望小唐可以一直坚持的学习,坚持写博客和交流知识。慢慢走,每一步都算数的。

    ✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!

    代码------→【gitee:唐棣棣 (TSQXG) - Gitee.com

    联系------→【邮箱:2784139418@qq.com】

  • 相关阅读:
    SQL-DCL
    docker到底能在哪些平台安装?
    浅析 SQL Server 的 CROSS APPLY 和 OUTER APPLY 查询 - 第一部分
    shin-monitor源码分析
    大二学生JavaScript实训大作业——动漫秦时明月7页 期末网页制作 HTML+CSS+JavaScript 网页设计实例 企业网站制作
    前端实现打印功能Print.js
    Pytorch实现鸟类品种分类识别(含训练代码和鸟类数据集)
    Learning Opencv3 p709有一个地方写错了
    STM32收入高也好找工作,所以我学嵌入式linux终究是错付了吗
    机械设计基础习题
  • 原文地址:https://blog.csdn.net/m0_74841364/article/details/133586033