阅读this Skip List implementation我遇到了这段代码:
typedef struct nodeStructure{
keyType key;
valueType value;
node forward[1]; /* variable sized array of forward pointers */
};
对我来说,似乎forward[1]
表示一个元素数组。评论称它为可变大小的数组。
我是否误解了某些内容,或者这只是我正在阅读的来源中的一个错误?
答案 0 :(得分:5)
它被称为 struct hack 。它是C99中引入的灵活数组成员的旧形式。
过去曾使用它来模仿结构的最后一个成员中的变量数组,但它不是C中严格符合的结构。
答案 1 :(得分:3)
这是C中的一个程序范例,有时你会看到。分配结构时,您将分配sizeof(struct nodeStructure + numNodes * sizeof(node))。
这允许您为struct提供多个前向节点,即使它只声明有一个。这是一个丑陋的黑客,但它的工作原理。
通常情况下,执行此操作时,还会有一个名为“count”的字段,以便您知道节点后面有多少额外条目。
答案 2 :(得分:2)
这是旧C编译器的常见技巧(在C99之前):当编译器是forward
的最后一个元素时,编译器允许您取消引用超过struct
声明长度结尾的元素。 ;然后,您可以malloc
为node
个元素添加足够的内存,如下所示:
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
,但是您需要将malloc
和free
与nodeStructure
分开,不必要地加倍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接受这些作为正确使用的扩展名。