/* 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;
}