当前位置: 首页 > article >正文

【C语言】一篇带你了解 柔性数组的意义与如何使用

文章目录

  • 柔性数组
  • 柔性数组的特点:
  • 柔性数组的使用
  • 柔性数组的优势

柔性数组

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

例如:

typedef struct S
{
	int i;
	int a[0];//柔性数组成员
}S;

有些编译器会报错无法编译可以改成:

typedef struct S
{
	int i;
	int a[];//柔性数组成员
}S;

柔性数组的特点:

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

柔性数组的使用

代码1

#include<stdio.h>
#include<stdlib.h>
typedef struct S
{
	int i;
	int a[];//柔性数组成员
}S;

int main()
{
	//分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
	S* s = (S*)malloc(sizeof(S) * sizeof(int) * 10);
    //判断s是否开辟成功
	if (s == NULL)
		perror("malloc:");

	//使用
	s->i = 100;
	int i = 0;

	//柔性数组使用
	for (i = 0; i < 10; i++)
	{
		s->a[i] = i;
	}
    //打印
	for (i = 0; i < 10; i++)
	{
		printf("%d ", s->a[i]);
	}
    //释放空间
    free(s);
	system("pause");
	return 0;
}

最终输出结果
0 1 2 3 4 5 6 7 8 9


柔性数组的优势

代码2

上述的 struct S结构也可以设计为结构中指针方案

#include<stdio.h>
#include<stdlib.h>
//代码2
typedef struct S
{
	int i;
	int* pa;//柔性数组成员
}S;

int main()
{
	S* s = (S*)malloc(sizeof(S));
	//判断s是否开辟成功
	if (s == NULL)
		perror("malloc:");

	int* ptr = (int*)malloc(sizeof(int) * 10);
	//判断是否开辟成功
	if (s->pa == NULL)
		perror("malloc:");
	else
		//开辟成功就还给s->pa使用
		s->pa = ptr;

	//使用
	s->i = 10;
	int i = 0;

	for (i = 0; i < 10; i++)
	{
		s->pa[i] = i;
	}

	for (i = 0; i < 10; i++)
	{
		printf("%d ", s->pa[i]);
	}

	//释放空间
	//先释放s->pa,如果先释放s就找不到s->pa了
	free(s->pa);
	s->pa = NULL;
	free(s);
	s = NULL;
	system("pause");
	return 0;
}

上述 代码1 和 代码2 可以完成同样的功能,但是 方法1 的实现有两个好处:

  • 代码1:
    malloc 1次 free 1次, 容易维护空间,不易出错malloc次数少,内存碎片就会较少,内存的使用率就较高一些

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

  • 代码2
    malloc 2次,free 2次,维护难度加大,容易出错内存碎片就会增多,内存的使用率就下降了

在这里插入图片描述



http://www.kler.cn/a/6802.html

相关文章:

  • 2024年低压电工证考试题库及低压电工试题解析
  • 计算机网络-MSTP基础实验一(单域多实例)
  • springboot如何获取控制层get和Post入参
  • 深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解
  • 主机型入侵检测系统(HIDS)——Elkeid在Centos7的保姆级安装部署教程
  • Python中的with语句
  • 计算机信息安全有哪些SCI期刊推荐? - 易智编译EaseEditing
  • useMemo和useCallback使用场景
  • 软件测试-自动化测试面试基础相关
  • 想成为一名【黑客】,你该如何快速的入门?
  • 项目1新知识
  • SpringBoot简介
  • 【django开发手册】如何使用select_related进行一次连表查询
  • 时间状语前不用介词的几种情况
  • 力扣8. 字符串转换整数 (atoi) 15行极简C++ 代码一次遍历通过
  • 【面试】面试官问的几率较大的网络安全面试题
  • 最优清零方案 蓝桥杯 2138 python实现
  • Java初阶 ( String 类)
  • 【新2023Q2押题JAVA】华为OD机试 - 打折买水果
  • 浅谈JVM(二):类加载机制
  • 4_vim的高级用法配置
  • 【Redis】redis跟数据库的数据同步问题
  • 【蓝桥杯】【嵌入式组别】第八节:EEPROM
  • TCP报文的交互过程
  • 【FLEXPART】拉格朗日粒子扩散模式
  • 2023-Python实现有道翻译接口加密解密