零长度数组

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

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

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

用于动态长度数组。 您可以使用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,但这使得分配变得复杂,因为你必须在计算所需的内存时进行补偿。

它被称为“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]; }; 

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

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

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

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

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