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