C语言 零长度数组[重复]

lo8azlld  于 2023-03-17  发布在  其他
关注(0)|答案(3)|浏览(157)

此问题在此处已有答案

What's the need of array with zero elements?(5个答案)
5年前关闭。
最近我看到了一个结构定义,

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

现在我不知道为什么要声明list[0],我感兴趣的是为什么要用这个,它有什么优势吗?如果有,是什么?

dkqlctbz

dkqlctbz1#

这是用于动态长度数组的,你可以使用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中,为了达到同样的效果,您可以完全省略size文字。
在实现这些功能之前,您经常看到使用长度为1的代码来执行此操作,但这会使分配变得有点复杂,因为在计算所需内存时必须进行补偿。

g6ll5ycj

g6ll5ycj2#

这就是所谓的“结构黑客”。你可以search for it在SO或在网上。
注意,在C语言中声明大小为0的数组在形式上是非法的。你提供的代码甚至是不可编译的。大多数C编译器会接受大小为0的数组声明作为扩展,特别是因为它经常在“struct hack”的“lazy”版本中使用。(它可以依靠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中也是非法的。

brc7rcf0

brc7rcf03#

另一个优点是如果你的结构描述的是磁盘上/网络上的数据,如果cnt是0,那么数据大小可能只有cnt的长度。
我在这里只是为了确认我所担心的,list[0]是无效的。

相关问题