結構體中最後成員為一個數組(長度為零)與一個指標
阿新 • • 發佈:2019-02-09
1. 結構體中最後一個數組長度為零
typedef struct _ex_mng
{
unsigned int type;
unsigned int oper;
char data[0];
}ex_mng_t;
最近在專案常用到這樣子的一個結構體,最後一個成員為可變長的陣列。
char data[0]中的data並不是指標,是一個偏移量,這個偏移量指向的是a、b後面緊接著的空間,代表了該結構體後面資料的起始地址,所以它其實並不佔用任何空間,因此sizeof(struct _ex_mng) = 8。 使用起來非常方便,建立時,malloc一段結構體大小加上可變長資料長度的空間給它,可變長部分可按陣列的方式訪問,釋放時,直接把整個結構體free掉就可以了。
例子:
ex_mng_t *ex_mng;
int datalen = 100;
/* 申請記憶體(結構體以及data的記憶體)*/
ex_mng = (ex_mng_t *)malloc(sizeof(ex_mng_t) + datalen );
ex_mng->type = 1;
ex_mng->oper = 1;
strcpy(ex_mng->data, "success!");
在結構體中,我們定義了0長度的陣列,按理對ex_mng->data進行賦值時是屬於越界訪問,但是我們把結構體後面的datalen個長度的空間也一起申請了,所以該訪問是合法的!
2. 結構體中最後一個成員為指標
typedef struct _ex_mng
{
unsigned int type;
unsigned int oper;
char *data;
}ex_mng_t;
而如果是指標的話,使用時候需要初始化,並且佔用空間,sizeof(struct _ex_mng) = 12(32位)/sizeof(struct _ex_mng) = 12(64位)。使用方法一:
使用方法二:ex_mng_t *ex_mng; int datalen = 100; /* 申請記憶體(結構體) */ ex_mng = (ex_mng_t *)malloc(sizeof(ex_mng_t)); ex_mng->type = 1; ex_mng->oper = 1; /* 申請記憶體(data) */ ex_mng->data = malloc(sizeof(char)* datalen ); strcpy(ex_mng->data, "success!"); /* 釋放記憶體(data)*/ free(ex_mng->data); /* 釋放記憶體(結構體)*/ free(ex_mng);
ex_mng_t *ex_mng;
int datalen = 100;
/* 申請記憶體(結構體+data) */
ex_mng = (ex_mng_t *)malloc(sizeof(ex_mng_t) + sizeof(char)*datalen);
ex_mng->type = 1;
ex_mng->oper = 1;
/* ex_mng->data指向結構體後的記憶體 */
ex_mng->data = ((char *)ex_mng ) + sizeof(ex_mng_t);
strcpy(ex_mng->data, "success!");
/* 釋放記憶體(結構體+data)*/
free(ex_mng);
注意:結構體中最後一個數組長度為零,有些編譯器會報錯無法編譯,可以改成char data[1],或則char data[]。 總之,結構體最後使用0或1的長度陣列的原因,主要是為了方便的管理記憶體緩衝區,當使用指標時候(使用方法一時),不能分配一段連續的的記憶體,會增加記憶體的碎片化。