[英]Strange variable-sized array declaration
閱讀此Skip List實現,我遇到了這個代碼片段:
typedef struct nodeStructure{
keyType key;
valueType value;
node forward[1]; /* variable sized array of forward pointers */
};
對我來說,似乎forward[1]
表示一個元素數組。 並且注釋稱它為可變大小的數組 。
我是否誤解了某些內容,或者這只是我正在閱讀的來源中的一個錯誤?
它被稱為struct hack 。 它是C99中引入的靈活陣列成員的舊形式。
過去曾使用它來模仿結構的最后一個成員中的變量數組,但它不是C中嚴格符合的結構。
這是C中的程序范例,有時您會看到。 分配結構時,您將分配sizeof(struct nodeStructure + numNodes * sizeof(node))。
這允許您為結構提供多個前向節點,即使它只被聲明為具有一個。 這是一個丑陋的黑客,但它的工作原理。
通常,當您執行此操作時,還會有一個名為“count”的字段,以便您知道節點后面有多少額外條目。
這是舊的C編譯器(C99)之前常用的技巧:讓你解引用元素過去年底編譯器forward
的聲明長度時,這是最后一個元素struct
; 然后你可以為其他node
元素malloc
足夠的內存,如下所示:
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
S和潛在地增加內存碎片:
以下是上述片段在沒有黑客的情況下的外觀:
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);
EDIT (響應Adam Rosenfield的評論):C99允許您定義沒有大小的數組,如下所示: node forward[];
這稱為靈活陣列成員 ,它在C99標准的6.7.2.1.16部分中定義。
數據結構實現很可能是針對C90標准編寫的,C90標准沒有靈活的陣列成員 (在C99中添加)。 那時,通常在結構的末尾使用1或甚至0大小的(*)數組來允許訪問那里動態可變數量的元素。
注釋不應解釋為C99樣式的可變長度數組; 此外,在C99中,成員forward
的慣用和符合標准的定義是node forward[];
。 然后將具有這樣的成員的諸如struct nodeStructure
的類型稱為不完整類型 。 您可以定義指向它的指針,但是您不能定義此類型的變量或取其大小, node forward[0]
或node forward[1]
允許的所有操作,盡管這些操作可能與程序員的意圖不匹配。
(*)標准禁止0大小的數組,但GCC接受這些作為正確使用的擴展。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.