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; }
相關文章
相關標籤/搜索