首页 > 代码库 > 零长数组

零长数组

在看Linux内核的路由代码时,发现有如下的结构体定义:

 1 struct fib_table {
 2     unsigned char tb_id;
 3     unsigned tb_stamp;
 4     int  (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res);
 5     int  (*tb_insert)(struct fib_table *table, struct rtmsg *r,
 6      ……
 7     void  (*tb_select_default)(struct fib_table *table,
 8                                const struct flowi *flp, struct fib_result *res);
 9 
10     unsigned char tb_data[0];
11 };

其中,tb_data数组的长度为0,经过百度(blog.csdn.net/zhaqiwen/article/details/7904515)得知:长度为的数组在标准c和c++中是不允许的,如果使用长度为的数组,编译时会产生错误,提示数组长度不能为,但在GNUc中,这种用法却是合法的
对于长度为0的数组,在gcc手册中,有如下一段代码片段:

struct line {
    int length;
    char contents[0];
};

struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length);
thisline->length = this_length;

这段代码的主要含义是定义了一个结构体,并对其进行初始化。零长数组有以下几个特点:

1,不占内存空间,上面结构体的第二个成员变量contents[0]事实上是不占内存空间的,因此整个结构体的长度sizeof(struct line)为4;

2,零长数组指向的内存区域与其所在结构体占用的内存区域是连续的,当采用malloc为thisline指向的内容申请内存空间时,如上所示,申请了一段长度为结构体长度加可变长度的内存空间给结构体类型的指针,这时contents就指向申请的可变长度的内存空间。由于是一次申请的,所以这段可变长度的内存空间和前面的结构体长度的内存空间是连续的;

3,零长数组指向的内存可以采用数组的方式访问(指针也是可以的,没有什么差别)

4,统一释放,对于整个结构体,当不再使用时,可以使用free函数一次性对其进行释放,而不必像指针那样分别释放。