在標(biāo)準(zhǔn)C和C++中0長(zhǎng)數(shù)組如charArray[0]是不允許使用的,因?yàn)檫@從語(yǔ)義邏輯上看,是完全沒(méi)有意義的。
但是,GUN中卻允許使用,而且,很多時(shí)候,應(yīng)用在了變長(zhǎng)結(jié)構(gòu)體中,如:
StructPacket
{
Int state;
Int len;
Char cData[0]; //這里的0長(zhǎng)結(jié)構(gòu)體就為變長(zhǎng)結(jié)構(gòu)體提供了非常好的支持
};
首先對(duì)0長(zhǎng)數(shù)組做一個(gè)解釋?zhuān)?/span>
用途 :長(zhǎng)度為0的數(shù)組的主要用途是為了滿(mǎn)足需要變長(zhǎng)度的結(jié)構(gòu)體。
用法 :在一個(gè)結(jié)構(gòu)體的最后 ,申明一個(gè)長(zhǎng)度為0的數(shù)組,就可以使得這個(gè)結(jié)構(gòu)體是可變長(zhǎng)的。對(duì)于編譯器來(lái)說(shuō),此時(shí)長(zhǎng)度為0的數(shù)組并不占用空間,因?yàn)閿?shù)組名本身不占空間,它只是一個(gè)偏移量, 數(shù)組名這個(gè)符號(hào)本身代 表了一個(gè)不可修改的地址常量 (注意:數(shù)組名永遠(yuǎn)都不會(huì)是指針! ),但對(duì)于這個(gè)數(shù)組的大小,我們可以進(jìn)行動(dòng)態(tài)分配
請(qǐng)仔細(xì)理解后半部分,對(duì)于編譯器而言,數(shù)組名僅僅是一個(gè)符號(hào),它不會(huì)占用任何空間,它在結(jié)構(gòu)體中,只是代表了一個(gè)偏移量,代表一個(gè)不可修改的地址常量!
對(duì)于0長(zhǎng)數(shù)組的這個(gè)特點(diǎn),很容易構(gòu)造出變成結(jié)構(gòu)體,如緩沖區(qū),數(shù)據(jù)包等等:
Struct Buffer
{
Int len;
Char cData[0];
};
這樣的變長(zhǎng)數(shù)組常用于網(wǎng)絡(luò)通信中構(gòu)造不定長(zhǎng)數(shù)據(jù)包,不會(huì)浪費(fèi)空間浪費(fèi)網(wǎng)絡(luò)流量,比如我要發(fā)送1024字節(jié)的數(shù)據(jù),如果用定長(zhǎng)包,假設(shè)定長(zhǎng)包的長(zhǎng)度為2048,就會(huì)浪費(fèi)1024個(gè)字節(jié)的空間,也會(huì)造成不必要的流量浪費(fèi)
Struct packet
{
char data[2048];
}
packet p;
memcpy(p.data,"1024 datas.........",1024)
send(socket,(char*)&p,sizeof(p));
由于考慮到數(shù)據(jù)的溢出,變長(zhǎng)數(shù)據(jù)包中的data數(shù)組長(zhǎng)度一般會(huì)設(shè)置得足夠長(zhǎng)足以容納最大的數(shù)據(jù),因此packet中的data數(shù)組很多情況下都沒(méi)有填滿(mǎn)數(shù)據(jù),因此造成了浪費(fèi),而如果我們用變長(zhǎng)數(shù)組來(lái)進(jìn)行封包的話(huà),就不會(huì)造成浪費(fèi)(最多會(huì)造成4個(gè)字節(jié)的浪費(fèi),包頭的int型的len不屬于數(shù)據(jù)因此算是浪費(fèi)),如前面的Buffer結(jié)構(gòu)體,假如我們要發(fā)送1024個(gè)字節(jié),我們?nèi)绾螛?gòu)造這個(gè)數(shù)據(jù)包呢:
char *tmp = (char*)malloc(sizeof(Buffer)+1024) //這句代碼的作用是申請(qǐng)一塊連續(xù)的內(nèi)存空間,這塊內(nèi)存空間的長(zhǎng)度是Buffer的大小加上1024數(shù)據(jù)的大小,由兩部分構(gòu)成,sizeof(Buffer)和1024,如果仔細(xì)觀察的話(huà),會(huì)發(fā)現(xiàn)這種申請(qǐng)方法比第一種多了一段sizeof(Buffer)大小的空間,原因何在?如下
Buffer *p = (Buffer*)tmp;
p->len = 1024;
memcpy(p.cData,"1024 datas............",1024);
如上三行代碼,首先做一個(gè)強(qiáng)制類(lèi)型轉(zhuǎn)換,Buffer類(lèi)型的指針指向內(nèi)存的起始位置,這段內(nèi)存要分兩部分使用,前部分4個(gè)字節(jié)p->len,作為包頭(就是多出來(lái)的那部分),這個(gè)包頭是用來(lái)描述緊接著包頭后面的數(shù)據(jù)部分的長(zhǎng)度,這里是1024,所以前四個(gè)字節(jié)賦值為1024(既然我們要構(gòu)造不定長(zhǎng)數(shù)據(jù)包,那么這個(gè)包到底有多長(zhǎng)呢,因此,我們就必須通過(guò)一個(gè)變量來(lái)表明這個(gè)數(shù)據(jù)包的長(zhǎng)度,這就是len的作用),而緊接其后的內(nèi)存是真正的數(shù)據(jù)部分,通過(guò)p->cData定位到該部分的起始地址,最后,進(jìn)行一個(gè)memcpy()內(nèi)存拷貝,把要發(fā)送的數(shù)據(jù)填入到這段內(nèi)存當(dāng)中,最后:
send(socket,p,sizeof(Buffer)+1024);發(fā)送數(shù)據(jù)
聯(lián)系客服