C 語言之柔性數組

一 歷史

在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字段呢, 柔性數組 就是用來幹這個的。

#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...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章