零长度数组

时间:2011-01-14 11:49:24

标签: c structure

最近我遇到了一个结构定义,

struct arr {
    int cnt;
    struct {
        int  size;
        int *name;
    } list[0];
};

现在我不知道list[0]被宣布的原因。我感兴趣的是为什么使用它。它有什么优势吗?如果是,那是什么?

3 个答案:

答案 0 :(得分:18)

用于动态长度数组。您可以使用malloc()分配内存,并将数组驻留在结构的末尾:

struct arr *my_arr = malloc(sizeof *my_arr + 17 * sizeof *my_arr->list);
my_arr->cnt = 17;
my_arr->list[0].size = 0;
my_arr->list[1].name = "foo";

实际上能够使用0作为长度是(如评论中所指出的)GCC扩展。在C99中,您可以完全忽略大小文字以获得相同的效果。

在实现这些事情之前,你经常看到这个事情的长度为1,但这会使分配变得复杂,因为你必须在计算所需的内存时进行补偿。

答案 1 :(得分:11)

它被称为“struct hack”。您可以在SO或网上搜索

http://www.google.com/search?q=struct+hack&sitesearch=stackoverflow.com/questions

请注意,正式声明在C中声明大小为0的数组总是违法的。您正式提供的代码甚至无法编译。大多数C编译器都接受0大小的数组声明作为扩展,特别是因为它经常用于“结构黑客”的“懒惰”版本(它可以依靠sizeof来确定要分配多少内存,因为假设0大小的数组不会影响结构的总大小。

可以说更好的struct hack实现使用大小为1的数组

struct arr {
    int cnt;
    struct {
        int  size;
        int *name;
    } list[1];
};

它“更好”,因为它至少可以正式编译。为了在N中使用list元素为结构分配内存,使用标准offsetof

arr *a = malloc(offsetof(arr, list) + N * sizeof a->list);

在C99版本的语言规范中,通过无大小数组声明(带有空[])支持“struct hack”,因为0大小的数组声明在C99中也是非法的。

答案 2 :(得分:0)

另一个优点是,您的结构描述了磁盘/网络上的数据。如果cnt为0,则数据大小可能只是cnt的长度。

我在这里只是为了确认我害怕的事情,list[0]无效。