C語言 結構體中的零長度數組


/* C語言零長度數組大小和取值問題 */
#include <stdio.h> 
#include <stdlib.h>
#include <string.h>

struct str 
{
    int type;
    char s[0];//零長度的數組
};

struct foo
{
    int type;
    char *s;
};

void test()
{
    printf("str size is [%d]  \n", sizeof(struct str));    //打印 4
    /*
        使用GDB查看匯編代碼
        對於struct str 結構體中的 char s[0]來說,匯編代碼用了lea指令,lea   0x04(%rax),   %rdx
        對於struct foo 結構體中的 char*s來說,匯編代碼用了mov指令,mov 0x04(%rax),   %rdx
        lea全稱load effective address,是把地址放進去,而mov則是把地址里的內容放進去。
        訪問成員數組名其實得到的是數組的相對地址,而訪問成員指針其實是相對地址里的內容(這和訪問其它非指針或數組的變量是一樣的)
        對於數組 char s[10]來說,數組名 s 和 &s 都是一樣的。char s[0] 表示的是地址。char*s 表示的地址的內容
    */

     printf("foo size is [%d]  \n", sizeof(struct foo));    //32位機器上 打印8

     //零長度的數組的打印
     struct str s1;
     printf("Arrays of Length Zero print [%p] \n", s1.s);   
     printf("Arrays of Length Zero print [%p] \n", &s1.s);    //結果相同  打印的是char s[0] 的地址

     struct foo f1;
     //printf("Arrays of Length Zero print [%x] \n", f1.s);    //程序core down 驗證 char*s  訪問成員指針其實是相對地址里的內容

}

//驗證char s[]更多的類似於一個占位符
struct str1
{
    int length;
    int flags;
    char s[0];//零長度的數組(Flexible Array)
};

void test1()
{
    //零長度數組的占位符功能
    //注意  char s[]更多的類似於一個占位符,並非結構體成員,所以計算結構體大小時,並沒有char s[]
    printf("===size==='[%d]====\n", sizeof(struct str1));
}

int main()
{

    test1();
    printf("-----ok------\n");
    getchar();
    return 0;
}
/* C語言零長度數組使用 */
#include <stdio.h> 
#include <stdlib.h>
#include <string.h>

#define GTS_HDR(s) ((struct str *)((s)-(sizeof(struct str))))

struct str 
{
    int length;
    unsigned char flags;
    char s[0];//零長度的數組(Flexible Array)
};

/*
零長度的數組優勢
第一個優點是,方便內存釋放。如果我們的代碼是在一個給別人用的函數中,你在里面做了二次內存分配,並把整個結構體返回給用戶。
用戶調用free可以釋放結構體,但是用戶並不知道這個結構體內的成員也需要free,所以你不能指望用戶來發現這個事。所以,
如果我們把結構體的內存以及其成員要的內存一次性分配好了,並返回給用戶一個結構體指針,用戶做一次free就可以把所有的內存也給釋放掉。 第二個優點是,這樣有利於訪問速度。連續的內存有益於提高訪問速度,也有益於減少內存碎片。 零長度數組的具體使用可以參考redis中sds結構
*/ char * create(void) { int len = 32; struct str *s1 = NULL; s1 = calloc(1, sizeof(struct str) + len); //模仿redis中sds結構 s1->flags = 1; s1->length = len; //注意 char s[0]只是一個占位符,不占用實際內存空間,所以成員變量char s[0]的offset不是s1->s,而是s1+sizeof(struct str) //因此也不應該對外暴露struct str 結構,防止用戶操作struct str 的內存空間 strcpy((char *)s1 + sizeof(struct str), "hello world "); //錯誤示例 打印空 printf("====error show==[%s]=====\n", s1->s); return (char *)s1 + sizeof(struct str); } void test() { char * s = create(); printf("--s is -[%s]---\n", s); } int main() { test(); printf("-----ok------\n"); getchar(); return 0; }

 零長度數組只有GUN/GCC支持 別的廠家可能不支持,此時需要用 char data[1]來代替


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM