变长结构体
變長結構體
?
變長結構體是由gcc擴展的一種技術,它是指其最后一個成員的長度不固定(flexible array member,也叫柔性數組),先來看一個簡單的例子:
#include <stdlib.h> #include <stdio.h>#pragma pack(1) typedef struct {int a;char b[10];char *vector; } cq; #pragma pack()int main() {cq *a = malloc(sizeof(cq));char str[] = "hello";a->vector = malloc(sizeof(str));memcpy(a->vector, str, sizeof(str));printf("%s\n", a->vector); // "hello"printf("%d\n", sizeof(cq)); // 22 free(a->vector);free(a);return 0; }這段代碼中,結構體cq中的成員vector是一個指針,你在分配內存緩沖區時,就必須分配結構體一次,然后再分配結構體內的指針一次,(而此時分配的內存已經與結構體的內存不連續了,所以要分別管理即申請和釋放)。
而如果使用數組,那么只需要一次就可以全部分配出來,(見下面的例子),反過來,釋放時也是一樣,一次釋放。而使用指針,得先釋放結構體內的指針,再釋放結構體。還不能顛倒次序。其次,就是分配一段連續的的內存,減少內存的碎片化。
?
#include <stdlib.h> #include <stdio.h>#pragma pack(1) typedef struct {int a;char b[10];char vector[0]; // 可變數組 } cq; #pragma pack()int main() {char str[] = "hello";cq *a = malloc(sizeof(cq) + sizeof(str)); // decide amount usedmemcpy(a->vector, str, sizeof(str));printf("%s\n", a->vector); // "hello"printf("%d\n", sizeof(cq)); // 14 free(a);return 0; }例子中,打印出的結構體長度是14(為成員a和b的長度之和),——變長數組vector不占結構體的空間!
可見,變長結構體是能讓我們在分配時再決定其大小,而不是在定義時就要固定其數組長度。
?
可變數組的一種更通用的用法是用一個成員指明變長數組的長度,方便在其他地方讀取數組內容。
struct line {int length;char contents[0]; };struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length); thisline->length = this_length;?
?
最后,轉述一段C99標準(draft N1570)對這個問題的描述,本人英文很爛,就不翻譯了。
As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a ?exible array member. In most situations, the ?exible array member is ignored. In particular, the size of the structure is as if the ?exible array member were omitted except that it may have more trailing padding than the omission would imply. However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a ?exible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the ?exible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is unde?ned if any attempt is made to access that element or to generate a pointer one past it.
?
參考:
http://stackoverflow.com/questions/11733981/what-is-the-purpose-of-a-zero-length-array-in-a-struct
?
?
?
?
?
?
?
轉載于:https://www.cnblogs.com/chenny7/p/3657712.html
總結