在c99標準出來以前。若是要在某個結構體中使用字符串變時,爲了使字符串變量存儲地址能與結構體總體連在一塊兒,須要這樣實現數組
#include <stdio.h> #include <malloc.h> #include <string.h> typedef struct pen { int len; char *data;//字符串變量 }pen; int main(int argc, char **argv) { char str[] = "this is a string";//須要填入的字符串 /* 動態申請一個pen類型結構體變量, 它的大小爲,pen類型的自己長度, 再加上str(須要填入字符串的長度),再加1, */ struct pen *p = (struct pen*)malloc(sizeof(pen) + strlen(str) + 1); p->data= NULL; //設置p的長度爲目標字符串的長度 p->len = strlen(str); /* 將目標字符串拷貝到結構體對應的位置 此處爲何p+1以後指向的是pen結構體存儲空間後的位置,而不是隻加一呢? 由於此處的p+1偏移的是p指向類型大小的偏移量,什麼意思呢?p指向的類型爲pen類型的結構體, 而pen類型的結構體大小爲 len(4字節)加上 data(8個字節),因爲此處有內存對齊的狀況, 因此實際上pen大小爲 4 + 8 + 4(這個4爲內存對齊的多餘空間,若是再增長一個int類型的變量, pen的大小仍是爲16)=16字節 因此此處p+1向後偏移了16字節,經過下方地址打印能夠詳細看出 */ strcpy((char*)(p + 1), str); //int所佔字節數,不一樣機器不一樣。通常64位爲4字節 printf("sizeof(int): %ld\n", sizeof(int)); //上文已說明,16字節 printf("sizeof(pen): %ld\n", sizeof(pen)); //起始地址 printf("start: %p\n\n", (char*)p); //上文已說明,偏移後的地址 printf("(p+1) : %p\n", (char*)(p+1)); //偏移後,對應的字符串 printf("(char*)(p+1): %s\n\n", (char*)(p+1)); //結構體變量data的地址 printf("&(p->data): %p\n", &(p->data)); //數據,null,此處爲空,故此變量已經被浪費。訪問對應字符串數據須要(char *)(p+1) printf("p->data: %s\n\n", p->data); }
經過上文咱們能夠看到,data字段是一個被浪費的指針(8個字節)。而且咱們想取到結構體下的字符串變量時須要(char *)(p+1)寫這麼一串東西,既很差看,也容易出錯,那有沒有能夠直接用p->data
取到字符串而且內存是連續的,並且又不浪費data
字段呢, 柔性數組 就是用來幹這個的。flex
#include <stdio.h> #include <malloc.h> #include <string.h> typedef struct pen { int len; char data[];//柔性數組 }pen; int main(int argc, char **argv) { char str[] = "this is a new string";//須要填入的字符串 struct pen *p = (struct pen*)malloc(sizeof(pen) + strlen(str) + 1); p->data= NULL; p->len = strlen(str); strcpy((char *)(p+1), str); printf("pen->data: %s\n", p->data); }
C99使用不完整類型實現柔性數組成員,在C99 中,結構中的最後一個元素容許是未知大小的數組,這就叫作柔性數組(flexible array)成員(也叫伸縮性數組成員),但結構中的柔性數組成員前面必須至少一個其餘成員。柔性數組成員容許結構中包含一個大小可變的數組。柔性數組成員只做爲一個符號地址存在,並且必須是結構體的最後一個成員,sizeof 返回的這種結構大小不包括柔性數組的內存 (此段話摘自:https://blog.csdn.net/ce123_z...)this