C语言柔性数组

柔性数组

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

struct S {
	int n;
	int arr[0];//未知大小的-柔性数组成员-数组的大小是可以调整的
	//int arr[];//也可以这么写
};
int main() {
	struct S* ps = (struct S*)malloc(sizeof(int) + 5 * sizeof(int));
	ps->n = 100;
	for (int i = 0; i < 5; i++) {
		ps->arr[i] = i;
	}
	//假设此处内存不够用,我们想要扩容
	struct S* ptr = (struct S*)realloc(ps, 100);
	if (ptr != NULL) {
		ps = ptr;
	}
	for (int j = 5; j < 10; j++) {
		ps->arr[j] = j;
	}

	free(ps);
	ps = NULL;
	return 0;
}

使用:

struct S* ps = (struct S*)malloc(sizeof(struct S));

结构体指针ps维护一块动态开辟的结构体内存空间
开辟的结构体内存空间存放int n(4字节)和int *arr(4字节),arr是一个指针指向一个地址

ps->arr = (int*)malloc(5 * sizeof(int));

在arr指向的地址上再动态开辟一块内存空间,用arr维护,arr指向的这块空间可以由我们自己设定
在这里插入图片描述
在这里插入图片描述

代码:

struct S {
	int n;
	int* arr;
};
int main() {
	struct S* ps = (struct S*)malloc(sizeof(struct S));//结构体指针ps维护一块动态开辟的结构体内存空间
	//开辟的结构体内存空间存放int n和int *arr,arr是一个指针指向一块空间
	ps->arr = (int*)malloc(5 * sizeof(int));//在arr指向的地址上再动态开辟一块内存空间,用arr维护
	for (int i = 0; i < sizeof(ps->arr) / sizeof(ps->arr[0]); i++) {
		ps->arr[i] = i;
	}
	//扩容
	int* ptr = (int*)realloc(ps, 10 * sizeof(int));
	if (ptr != NULL) {
		ps->arr = ptr;
	}
	for (int i = 5; i < sizeof(ps->arr)/sizeof(ps->arr[0]); i++) {
		ps->arr[i] = i;
		//这里动态开辟一块连续存储5个字节的的内存空间--类似于数组,arr维护这块空间,相当于数组首元素地址,故可以用arr[i]方式访问
		
	}
	free(ps->arr);
	free(ps);
	ps = NULL;
	return 0;
}

关于C语言realloc、malloc、free函数讲解

柔性数组的特点:

·结构中的柔性数组成员前面必须至少一个其他成员。
sizeof返回的这种结构大小不包括柔性数组的内存。
在这里插入图片描述

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

柔性数组的好处

第一个好处是:方便内存释放
如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。
第二个好处是:这样有利于访问速度.
连续的内存有益于提高访问速度,也有益于减少内存碎片。(其实,我个人觉得也没多高了,反正你跑不了要用做偏移量的加法来寻址)

扩展阅读:
C语言结构体里的数组和指针

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值