零长度数组

hue*_*hue 12 c structure

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

struct arr {
    int cnt;
    struct {
        int  size;
        int *name;
    } list[0];
};
Run Code Online (Sandbox Code Playgroud)

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

unw*_*ind 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";
Run Code Online (Sandbox Code Playgroud)

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

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

  • 除此之外,作为一个0长度的数组,`list`对结构的大小没有贡献.`sizeof(struct arr)== 4` (5认同)
  • 使用长度"0"的能力是GCC特征.C99等价物是完全保留长度,如`struct {...} list [];` (4认同)
  • @hue:呃......你刚才得到了两个描述这种优势的答案.它允许您为结构分配内存,并为结构末尾的数组的可变长度分配*一个连续的内存块*,一次调用`malloc`.如果您使用了指针,则必须单独分配内存(两个`malloc`调用,可能是非连续的)或使用其他一些技巧(以实现正确的对齐等) (4认同)
  • @hue:不 - 这会将你的列表数组存储起来,并在内存中的其他位置进行malloc.这个列表紧跟在结构之后. (3认同)

AnT*_*AnT 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];
};
Run Code Online (Sandbox Code Playgroud)

它"更好",因为它至少可以正式编译.为了为包含N元素的结构分配内存list,使用标准offsetof

arr *a = malloc(offsetof(arr, list) + N * sizeof a->list);
Run Code Online (Sandbox Code Playgroud)

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