【C语言进阶】柔性数组

news/2025/2/22 18:34:01/

在这里插入图片描述
在这里插入图片描述

目录

  • 一:柔性数组的特点
  • 二:柔性数组的使用
  • 三:模拟实现柔性数组

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

以下是柔性数组的两种写法:

//写法一:
struct S
{int n;char c;char arr[];//数组大小没有写说明它的大小是未知的 - - 柔性数组成员
};//写法二:
struct S
{int n;char c;char arr[0];//0也说明它的大小是未知的 - - 柔性数组成员
};

一:柔性数组的特点

  • 结构体中的柔性数组成员前面必须至少一个其他成员
  • sizeof返回的这种结构体大小不包括柔性数组的大小
  • 包含柔性数组成员的结构体malloc函数进行动态内存分配,并且分配的内存应该大于结构体的大小,以适应柔性数组的预期大小。
//利用malloc进行空间分配
struct S
{int n;char arr[];//数组大小没有写说明它的大小是未知的 - - 柔性数组成员
};int main()
{printf("%d\n", sizeof(struct S));struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(char));//后面的10 * sizeof(char)就是为arr数组开辟的return 0;
}

二:柔性数组的使用

#include <stdio.h>
#include <stdlib.h>struct S
{int n;char arr[];//数组大小没有写说明它的大小是未知的 - - 柔性数组成员
};int main()
{printf("%d\n", sizeof(struct S));struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(char));//后面的10 * sizeof(char)就是为arr数组开辟的if (ps == NULL){perror("malloc");return 1;}//使用ps->n = 100;int i = 0;for (i = 0; i < 10; i++){ps->arr[i] = 'a';}for (i = 0; i < 10; i++){printf("%c ", ps->arr[i]);}//增容struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(char));if (ptr == NULL){perror("realloc");return 1;}else{ps = ptr;}//释放free(ps);ps = NULL;return 0;
}

三:模拟实现柔性数组

struct S
{int n;char* arr;
};int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S));if (ps == NULL){perror("malloc");return 1;}//为arr开辟指向的空间ps->arr = (char*)malloc(sizeof(char) * 10);//开辟10个字符型的空间if (ps->arr == NULL){perror("malloc");return 1;}//使用ps->n = 100;int i = 0;for (i = 0; i < 10; i++){ps->arr[i] = 'a';}for (i = 0; i < 10; i++){printf("%c ", ps->arr[i]);}//增容char* ptr = (char*)realloc(ps->arr, sizeof(char) * 20);if (ptr == NULL){perror("realloc");return 1;}else{ps->arr = ptr;}//使用for (i = 0; i < 20; i++){*((ps->arr)+i) = 'b';}for (i = 0; i < 20; i++){printf("%c ", *((ps->arr) + i));}//释放free(ps->arr);ps->arr = NULL;free(ps);ps = NULL;return 0;
}

 常规的柔性数组,只需要malloc一次,free一次,并且空间是连续的,而模拟实现的柔性数组需要malloc两次,free两次,并且空间可能不连续。malloc的次数越多,越容易出错,可能出现忘记释放导致内存泄漏问题。此外,malloc的次数越多,产生的内存碎片就越多,内存利用率就会下降,造成内存空间浪费,malloc次数越少,产生的北村碎片就越少,内存利用率就会增加,会避免内存空间浪费。并且空间连续的情况下,访问数据的时候效率就会更高。

 今天的分享到这里就结束啦!如果觉得文章还不错的话,记得三连支持一下小恐龙,您的支持就是小恐龙前进的动力!


在这里插入图片描述


http://www.ppmy.cn/news/20821.html

相关文章

不看后悔,一文入门Go云原生微服务

文章目录打好基础微服务框架对比简单横评各个框架微服务概念软件架构演进史简单理解微服务的好处go-micro概述构成组件Go MicroAPISidecarWebCLIBot总结Go Micro组件架构Registry注册中心Selector负载均衡Broker事件驱动&#xff1a;发布订阅Transport消息传输总结快速入门准备…

kotlin lambda表达式和简化

Lambda&#xff1a; 是一小段可以作为参数传递的代码&#xff0c; 作为实参 结构&#xff1a; {参数名1: 类型&#xff0c; 参数名1: 类型 -> 函数体} 最后一行代码会自动作为Lambda 表达式的返回值 思考一个需求&#xff1a; 在水果集合中找到字符最长的水果 val list l…

2023/1/30总结

今天写了俩个题目&#xff1a; 第一个&#xff1a;P3366 【模板】最小生成树 https://blog.csdn.net/lxh0113/article/details/128803915?spm1001.2014.3001.5502 第二个&#xff1a;P3371 【模板】单源最短路径&#xff08;弱化版&#xff09; https://blog.csdn.net/lxh…

Kafka API 学习

1. Producer 生产者 1.1 消息发送流程 Kafka 的 Producer发送消息采用的是 异步发送 的方式。在消息发送的过程中&#xff0c;涉及到了 两个线程 main线程和 Sender线程 &#xff0c;以及 一个线程共享变量 RecordAccumulator。 main线程将消息发送给 RecordAccumulator Send…

2023.1.30---TF-A相关

完成TF-A源码的移植过程在tf-a源码目录下将补丁文件打到tf-a源码中2.在上级目录中的Makefile.sdk文件中&#xff0c;配置交叉编译工具链&#xff0c;找到CROSS_COMPILE将红色部分改为arm-linux-gnueabihf-3.在fds目录下添加设备树文件4.在上级目录中的Makefile.sdk文件中&#…

游戏SDK(三)架构设计之代码实现1

前言 上一篇介绍了游戏SDK架构设计的思路&#xff0c;大体的项目结构如下&#xff1a; - sdk-demo // sdk 测试 demo - sdk-api // sdk 接口模块 - sdk-manager // sdk 业务分发管理 - sdk-channel // 登录支付渠道- sdk-channel-huawei // 具体的渠道sdk &#xf…

JAVA01_30学习总结(Spring入门)

今日内容 1. Spring引入 Spring是用来解耦的专用框架和工具,代替普通new的方式,利用反射! 2. 简单工厂模式 简单工厂模式-静态方法工厂模式该工厂模式的核心思想就是-利用配置文件的键值对特性,利用反射来获取需要的对象,不在使用new的方式,进行解耦!步骤1)构造方法私有化,…

(dfs模板)使用dfs算法时没有对回溯时的状态量进行恢复

模板&#xff1a; vector<int> path; vector<vector<int>> result; void backTracking(......) { if (......) { ...... return; } for (int i 0; i < size; i) { path.emplace_b…