C语言:0长度数组/可变数组/柔性数组

1. 0长度数组

C语言:0长度数组又叫做:可变数组或者柔性数组

1.1 代码例子

struct ZeroBuffer
{
	int len;
	char acData[0]; //这里的0长结构体就为变长结构体提供了非常好的支持
};

1.2 什么是0长度数组(可变数组/柔性数组)?

0长度数组既数组大小待定的数组, C语言中结构体的最后一个元素可以是大小未知的数组,也就是所谓的0长度,所以我们可以用结构体来创建0长度数组。

1.3 用途

长度为0的数组的主要用途是为了满足需要变长度的结构体

1.4 用法

在一个结构体的最后, 申明一个长度为0的数组, 就可以使得这个结构体是可变长的。
对于编译器来说, 此时长度为0的数组并不占用空间, 因为数组名本身不占空间, 它只是一个偏移量, 数组名这个符号本身代表了一个不可修改的地址常量

1.5 优点

比起在结构体中声明一个指针变量、再进行动态分配的办法,这种方法效率要高。
因为在访问数组内容时,不需要间接访问,避免了两次访存(两次寻址操作)。

1.6 缺点

在结构体中,数组为0的数组必须在最后声明,使用上有一定限制。

1.7 重点:数组名仅仅是一个符号

对于编译器而言, 数组名仅仅是一个符号, 它不会占用任何空间, 它在结构体中, 只是代表了一个偏移量, 代表一个不可修改的地址常量!

即 sizeof(struct ZeroBuffer) = sizeof(int)

1.8 GNU Document中 变长数组的支持

在 C90 之前, 并不支持0长度的数组, 0长度数组是 GNU C 的一个扩展, 因此早期的编译器中是无法通过编译的

2. 代码测试例(0长度的数组,定长数组,指针数组)

// zero_length_array.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LENGTH      1024
#define CURR_LENGTH      512

//  0长度数组
typedef struct zero_buffer
{
	int     len;
	char    data[0];
}ZERO_BUFFER;


//  定长数组
typedef struct max_buffer
{
	int     len;
	char    data[MAX_LENGTH];
}MAX_BUFFER;


//  指针数组
typedef struct point_buffer
{
	int     len;
	char    *data;
}POINT_BUFFER;

int main(void)
{
	ZERO_BUFFER  *zbuffer = NULL;
	MAX_BUFFER   *mbuffer = NULL;
	POINT_BUFFER *pbuffer = NULL;


	// =====================
	// 0长度数组  占用-开辟-销毁
	// =====================
	///  占用
	printf("the length of struct zero_buffer:%d\n", sizeof(struct zero_buffer));
	///  开辟
	if ((zbuffer = (struct zero_buffer *)malloc(sizeof(struct zero_buffer) + sizeof(char) * CURR_LENGTH)) != NULL)
	{
		zbuffer->len = CURR_LENGTH;
		memcpy(zbuffer->data, "Hello World", CURR_LENGTH);


		printf("%d, %s\n", zbuffer->len, zbuffer->data);
	}
	///  销毁
	free(zbuffer);
	zbuffer = NULL;


	// =====================
	// 定长数组  占用-开辟-销毁
	// =====================
	///  占用
	printf("the length of struct max_buffer:%d\n",sizeof(struct max_buffer));
	///  开辟
	if ((mbuffer = (struct max_buffer *)malloc(sizeof(struct max_buffer))) != NULL)
	{
		mbuffer->len = CURR_LENGTH;
		memcpy(mbuffer->data, "Hello World", CURR_LENGTH);


		printf("%d, %s\n", mbuffer->len, mbuffer->data);
	}
	/// 销毁
	free(mbuffer);
	mbuffer = NULL;

	// =====================
	// 指针数组  占用-开辟-销毁
	// =====================
	///  占用
	printf("the length of struct point_buffer:%d\n",sizeof(struct point_buffer));
	///  开辟
	if ((pbuffer = (struct point_buffer *)malloc(sizeof(struct point_buffer))) != NULL)
	{
		pbuffer->len = CURR_LENGTH;
		if ((pbuffer->data = (char *)malloc(sizeof(char) * CURR_LENGTH)) != NULL)
		{
			memcpy(pbuffer->data, "Hello World", CURR_LENGTH);


			printf("%d, %s\n", pbuffer->len, pbuffer->data);
		}
	}
	/// 销毁
	free(pbuffer->data);
	free(pbuffer);
	pbuffer = NULL;


	return EXIT_SUCCESS;
}

结果:

the length of struct zero_buffer:4
512, Hello World
the length of struct max_buffer:1028
512, Hello World
the length of struct point_buffer:16
512, Hello World

说明:
	1. 长度为0的数组并不占有内存空间, 而指针方式需要占用内存空间.
	2. 对于长度为0数组, 在申请内存空间时, 采用一次性分配的原则进行; 
	3. 对于包含指针的结构体, 才申请空间时需分别进行, 释放时也需分别释放.

3. 参考:

https://blog.csdn.net/gatieme/article/details/64131322
https://github.com/gatieme/AderXCoding/tree/master/language/c/zero_length_array

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值