1. 程式人生 > >結構體中最後成員為一個數組(長度為零)與一個指標

結構體中最後成員為一個數組(長度為零)與一個指標

1. 結構體中最後一個數組長度為零

typedef struct _ex_mng
{
    unsigned int type;
    unsigned int oper;
    char data[0];
}ex_mng_t;
    最近在專案常用到這樣子的一個結構體,最後一個成員為可變長的陣列。
    char data[0]中的data並不是指標,是一個偏移量,這個偏移量指向的是a、b後面緊接著的空間,代表了該結構體後面資料的起始地址,所以它其實並不佔用任何空間,因此sizeofstruct  _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;
而如果是指標的話,使用時候需要初始化,並且佔用空間,sizeofstruct _ex_mng) = 1232位)/sizeofstruct _ex_mng) = 1264位)。
使用方法一:  
   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[] 總之,結構體最後使用01的長度陣列的原因,主要是為了方便的管理記憶體緩衝區,當使用指標時候(使用方法一時),不能分配一段連續的的記憶體,會增加記憶體的碎片化。