面對一個人的大型C/C++程序時,只看其對struct 的使用情況我們就可以對其編寫者的編程經驗進行評估。因為一個
大型的C/C++程序,勢必要涉及一些(甚至大量)進行數據組合的結構體,這些結構體可以將原本意義屬于一個整體的數據組合在一起。從某種程度上來
說,會不會用struct,怎樣用struct 是區別一個開發人員是否具備豐富開發經歷的標志。
在網絡協議、通信控制、嵌入式系統的C/C++編程中,我們經常要傳送的不是簡單的字節流(char型數組),而是多種數據組合起來的一個整體,其表現形式是一個
結構體。經驗不足的開發人員往往將所有需要傳送的內容依順序保存在char 型數組中,通過指針偏移的方法傳送網絡報文等信息。這樣做編程復雜,易
出錯,而且一旦控制方式及通信協議有所變化,程序就要進行非常細致的修改。
一個有經驗的開發者則靈活運用結構體,舉一個例子,假設網絡或控制協議中需要傳送三種報文,其格式分別為packetA、packetB、packetC:
struct structA
{
int a;
char b;
};
struct structB
{
char a;
short b;
};
struct structC
{
int a;
char b;
float c;
}
優秀的程序設計者這樣設計傳送的報文:
struct CommuPacket
{
int iPacketType;
//報文類型標志
union
//每次傳送的是三種
報文中的一種,使用union
{
struct structA packetA; struct structB packetB;
struct structC packetC;
}
};
在進行報文傳送
時,直接傳送struct CommuPacket 一個整體。
假設發送函數的原形如下:
// pSendData:發送字節流的首地址,iLen:要發送的長度
Send(char * pSendData, unsigned int iLen);
發送方可以直接進行如下調用發送struct CommuPacket 的一個實例sendCommuPacket:
Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );
假設接收函數的原
形如下:
// pRecvData:發送字節流的首地址,iLen:要接收的長度
//返回值:實際接收到的字節數
unsigned int Recv(char * pRecvData, unsigned int iLen);
接收方可以直接進行如下調用將接收到的數據保存在struct
CommuPacket 的一個實例recvCommuPacket
中:
Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );
接著判斷報文類型進行相應處理:
switch(recvCommuPacket. iPacketType)
{
case PACKET_A:
…
//A 類報文處理
break;
case PACKET_B:
…
//B 類報文處理
break;
case PACKET_C:
…
//C 類報文處理
break;
}
以上程序中最值得注意的是
Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );
Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );
中的強制類型轉換:(char *)&sendCommuPacket、(char *)&recvCommuPacket,
先取地址,再轉化為char 型指針,這樣就可以直接利用處理字節流的函數。
利用這種強制類型轉化,我們還可以方便程序的編寫,例如要
對sendCommuPacket
所處內存初始化為0,可以這樣調用標準庫函數memset():
memset((char *)&sendCommuPacket,0, sizeof(CommuPacket));
原文; http://www.arm16.com/viewthread.php?tid=397