最近我遇到了一个结构定义,
struct arr {
int cnt;
struct {
int size;
int *name;
} list[0];
};
现在我不知道list[0]
被宣布的原因。我感兴趣的是为什么使用它。它有什么优势吗?如果是,那是什么?
答案 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]
无效。