在標準C和C++中0長數組如charArray[0]是不容許使用的,由於這從語義邏輯上看,是徹底沒有意義的。數組
可是,GUN中卻容許使用,並且,不少時候,應用在了變長結構體中,如:網絡
StructPacketsocket
{spa
Int state;.net
Int len;指針
Char cData[0]; //這裏的0長結構體就爲變長結構體提供了很是好的支持blog
};內存
首先對0長數組作一個解釋:編譯器
用途 :長度爲0的數組的主要用途是爲了知足須要變長度的結構體。編譯
用法 :在一個結構體的最後 ,申明一個長度爲0的數組,就可使得這個結構體是可變長的。對於編譯器來講,此時長度爲0的數組並不佔用空間,由於數組名自己不佔空間,它只是一個偏移量, 數組名這個符號自己代 表了一個不可修改的地址常量 (注意:數組名永遠都不會是指針! ),但對於這個數組的大小,咱們能夠進行動態分配
請仔細理解後半部分,對於編譯器而言,數組名僅僅是一個符號,它不會佔用任何空間,它在結構體中,只是表明了一個偏移量,表明一個不可修改的地址常量!
對於0長數組的這個特色,很容易構造出變成結構體,如緩衝區,數據包等等:
Struct Buffer
{
Int len;
Char cData[0];
};
這樣的變長數組經常使用於網絡通訊中構造不定長數據包,不會浪費空間浪費網絡流量,好比我要發送1024字節的數據,若是用定長包,假設定長包的長度爲2048,就會浪費1024個字節的空間,也會形成沒必要要的流量浪費
Struct packet
{
char data[2048];
}
packet p;
memcpy(p.data,"1024 datas.........",1024)
send(socket,(char*)&p,sizeof(p));
因爲考慮到數據的溢出,變長數據包中的data數組長度通常會設置得足夠長足以容納最大的數據,所以packet中的data數組不少狀況下都沒有填滿數據,所以形成了浪費,而若是咱們用變長數組來進行封包的話,就不會形成浪費(最多會形成4個字節的浪費,包頭的int型的len不屬於數據所以算是浪費),如前面的Buffer結構體,假如咱們要發送1024個字節,咱們如何構造這個數據包呢:
char *tmp = (char*)malloc(sizeof(Buffer)+1024) //這句代碼的做用是申請一塊連續的內存空間,這塊內存空間的長度是Buffer的大小加上1024數據的大小,由兩部分構成,sizeof(Buffer)和1024,若是仔細觀察的話,會發現這種申請方法比第一種多了一段sizeof(Buffer)大小的空間,緣由何在?以下
Buffer *p = (Buffer*)tmp;
p->len = 1024;
memcpy(p.cData,"1024 datas............",1024);
如上三行代碼,首先作一個強制類型轉換,Buffer類型的指針指向內存的起始位置,這段內存要分兩部分使用,前部分4個字節p->len,做爲包頭(就是多出來的那部分),這個包頭是用來描述緊接着包頭後面的數據部分的長度,這裏是1024,因此前四個字節賦值爲1024(既然咱們要構造不定長數據包,那麼這個包到底有多長呢,所以,咱們就必須經過一個變量來代表這個數據包的長度,這就是len的做用),而緊接其後的內存是真正的數據部分,經過p->cData定位到該部分的起始地址,最後,進行一個memcpy()內存拷貝,把要發送的數據填入到這段內存當中,最後:
send(socket,p,sizeof(Buffer)+1024);發送數據
轉自:http://blog.csdn.net/yby4769250/article/details/7294696