程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C語言中的柔性數組

C語言中的柔性數組

編輯:關於C

今天浏覽酷殼上一篇文章http://coolshell.cn/articles/11377.html時,發現了有關“零長度的數組”的一些知識,其實之前在論壇中也見過這種用法,但是當時對此不太理解,時間一長就慢慢淡忘了該知識點。於是今天特意查了資料,總算弄清“零長度的數組”即柔性數組這一知識點,現在記錄如下。


零長度的數組一般見於結構體中,而直接聲明零長度數組,例如,

char str[0];
是無法編譯通過的。而網上說零長度的數組一般是放在結構體的最後一個成員的位置處,但是我試了下,放在中間也是可以的。

先說說放在最後位置處的情況:

結構體聲明如下:

struct str
{
	int len;
	int b;
	char s[0];
};
注意這裡可能也無法編譯通過,沒關系,改為char s[];這樣就可以了。這裡的char s[0]指的是一個變長數組,也相當於指針吧,不過跟指針卻有本質的區別,如果聲明成指針,那麼指針指向的內存空間可能跟成員b的空間不連續,而聲明成char s[0]則是連續的。

這裡你可能對結構體struct str的大小不太明確,到底是是多少呢?經過測試發現是8,即sizeof(int) + sizeof(int),也就是說s指向的空間不屬於結構體str,這塊空間緊跟著結構體str所代表的空間。

上文指出char s[0]指向的空間緊跟著結構體所代表的空間,因此對於一個struct str *型的指針變量申請內存有如下方法:

s = (struct str *)malloc(sizeof(struct str) + 10);
表示給s申請了10個字節的空間。
下面看一個例子:

#include 
#include 
#include 

struct str
{
	int len;
	int b;
	char s[0];
};


int main(int argc, char *argv[])
{
	struct str *s = NULL;
	
	printf("sizeof(struct str) = %d\n", sizeof(struct str));
	
	s = (str *)malloc(sizeof(struct str) + 10);
	s->len = 100;
	s->b = 50;
	
	strcpy(&s->s[0], "abc");
	puts(s->s);
	
	printf("sizeof(struct str) = %d\n", sizeof(struct str));
	
	printf("addr of len = %p, value of len = %d\n", &s->len, s->len);
	printf("addr of b = %p, value of b = %d\n", &s->b, s->b);
	printf("addr of s = %p, value of s = %s\n", &s->s, s->s);
	
	return 0;
}


執行結果為:

sizeof(struct str) = 8
abc
sizeof(struct str) = 8
addr of len = 0x9831008, value of len = 100
addr of b = 0x983100c, value of b = 50
addr of s = 0x9831010, value of s = abc

可以看出s確實是排在成員b的後面!盡管表面上看s是結構體str的成員,但實際上並不是;這樣做的好處就是可以一次性將所需的內存空間申請出來(所以內存是連續的,內存碎片也減少了),因為如果是以指針形式聲明的,那麼就必須做兩次內存申請(結構體一次,成員s一次)。

再看看成員char s[0]放在結構體中間位置處:

#include 
#include 
#include 

struct str
{
	int len;
	char s[0];
	int b;
};


int main(int argc, char *argv[])
{
	struct str *s = NULL;
	
	printf("sizeof(struct str) = %d\n", sizeof(struct str));
	
	s = (str *)malloc(sizeof(struct str) + 10);
	s->len = 100;
	s->b = 50;
	
	strcpy(&s->s[0], "abc");
	puts(s->s);
	
	printf("sizeof(struct str) = %d\n", sizeof(struct str));
	
	printf("addr of len = %p, value of len = %d\n", &s->len, s->len);
	printf("addr of s = %p, value of s = %s\n", &s->s, s->s);
	printf("addr of b = %p, value of b = %d\n", &s->b, s->b);
	
	return 0;
}

執行結果為:

sizeof(struct str) = 8
abc
sizeof(struct str) = 8
addr of len = 0x8da6008, value of len = 100
addr of s = 0x8da600c, value of s = abc
addr of b = 0x8da600c, value of b = 6513249

可以清楚的看出s和b的地址是一樣的,對s賦值,結果將b的值給覆蓋了,有點像聯合體哈!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved