作者:Sam (甄峰) sam_code@hotmail.com
在Linux Kernel或一些GNU项目中,可以看到长度设定为0的数组。之前没有深究,这次研究一下。
以下内容大量摘抄网上信息。
标准C和C++不支持0长度数组。如果定义0长数组。编译阶段就会报错。但GNU
C支持零长数组,条件是作为结构体的最后一项。
但这一项因为长度为0,所以不占空间。
举例如下:
#include
//stdio.h
#include
//sys/types.h
#include
//stdint.h
#include // stdlib.h
typedef struct {
uint8_t subevent;
uint8_t data[0];
} __attribute__ ((packed)) test_event;
int main(int argc, char** argv)
{
int ext_size = 12;
char Letter = 'A';
printf("\nSize is: %d\n", sizeof(test_event));
test_event* event = (test_event*) malloc(sizeof(test_event)+
9);
for(int i = 0; i < ext_size; i++)
{
event->data[i] = Letter++;
}
printf("\n");
for(int i = 0; i < ext_size; i++)
{
printf("%c\t", event->data[i]);
}
return 0;
}
可以看到结果是:
Size is: 1
A B
C
D
E
F
G
H
I
J
K
L
这个用法主要用于变长Buffer。 结构体大小为1, data[0]不占任何空间。
如果采用另一个方法,比如把data设置为指针,也可以实现此功能。但首先这个执针本身需要占用4bytes.
而且还需要申请新内存再要指针指向它。
这样的话,内存不连续,且要分别管理。
而是用零长度数组。申请时,内存长度为机构体长度+数组长度。内存空间连续。释放时也只需释放一次。
用途 :长度为0的数组的主要用途是为了满足需要变长度 的结构体。
用法 :在一个结构体的最后 ,申明一个长度为0的数组,就可以使得这个结构体是可变长的。对于 编译器来说,此时长度为0的数组并不占用空间,因为数组名本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针! ),但对于这个数组的大小,我们可以进行动态分配。例如:
typedef
struct{
int len;
char data[0];
}test_t;
int my_length = 10;
test_t *p_test =
(test_t *)malloc(sizeof(test_t) + my_length);
p_test->len = my_length;
......
free(p_test);
之后对于结构体中的数组可以像一般的数组一样进行访问。