奇怪的可变大小的数组声明

时间:2012-11-08 20:01:01

标签: c arrays

阅读this Skip List implementation我遇到了这段代码:

typedef struct nodeStructure{
    keyType key;
    valueType value;
    node forward[1]; /* variable sized array of forward pointers */
    };

对我来说,似乎forward[1]表示一个元素数组。评论称它为可变大小的数组

我是否误解了某些内容,或者这只是我正在阅读的来源中的一个错误?

4 个答案:

答案 0 :(得分:5)

它被称为 struct hack 。它是C99中引入的灵活数组成员形式。

过去曾使用它来模仿结构的最后一个成员中的变量数组,但它不是C中严格符合的结构。

答案 1 :(得分:3)

这是C中的一个程序范例,有时你会看到。分配结构时,您将分配sizeof(struct nodeStructure + numNodes * sizeof(node))。

这允许您为struct提供多个前向节点,即使它只声明有一个。这是一个丑陋的黑客,但它的工作原理。

通常情况下,执行此操作时,还会有一个名为“count”的字段,以便您知道节点后面有多少额外条目。

答案 2 :(得分:2)

这是旧C编译器的常见技巧(在C99之前):当编译器是forward的最后一个元素时,编译器允许您取消引用超过struct声明长度结尾的元素。 ;然后,您可以mallocnode个元素添加足够的内存,如下所示:

nodeStructure *ptr = malloc(sizeof(nodeStructure)+4*sizeof(node));
for (int i = 0 ; i != 5 ; i++) { // The fifth element is part of the struct
    ptr->forward[i] = ...
}
free(ptr);

该技巧允许您在结构中嵌入可变大小的数组,而无需单独的动态分配。另一种解决方案是声明node *forward,但是您需要将mallocfreenodeStructure分开,不必要地加倍malloc并且可能增加内存碎片:

以下是上述片段在没有黑客的情况下的外观:

typedef struct nodeStructure{
    keyType key;
    valueType value;
    node *forward;
};

nodeStructure *ptr = malloc(sizeof(nodeStructure));
ptr->forward = malloc(5*sizeof(node));
for (int i = 0 ; i != 5 ; i++) {
    ptr->forward[i] = ...
}
free(ptr->forward);
free(ptr);

编辑(响应Adam Rosenfield的评论):C99允许您定义没有大小的数组,如下所示:node forward[];这称为灵活数组成员,它在C99标准的第6.7.2.1.16节中定义。

答案 3 :(得分:2)

数据结构实现很可能是针对C90标准编写的,该标准没有灵活的阵列成员(在C99中添加)。那时,通常在结构的末尾使用1或甚至0大小的(*)数组来允许访问那里动态可变数量的元素。

注释不应解释为C99样式的可变长度数组;此外,在C99中,成员forward的惯用语和符合标准的定义将是node forward[];。然后将具有此类成员的struct nodeStructure类型称为不完整类型。您可以定义指向它的指针,但是您无法定义此类型的变量或采用其大小,node forward[0]node forward[1]允许的所有操作,尽管这些操作可能与程序员的意图不匹配。

(*)标准禁止0大小的数组,但GCC接受这些作为正确使用的扩展名。