程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 字節序轉換與結構體位域(bit field)值的讀取,bitfield

字節序轉換與結構體位域(bit field)值的讀取,bitfield

編輯:C++入門知識

字節序轉換與結構體位域(bit field)值的讀取,bitfield


最近又遇到了幾年前遇到的問題,標記一下。

 

對於跨字節位域(bit field)而言,如果數據傳輸前後環境的字節序不同(LE->BE,BE->LE),簡單地調用(ntohs/ntohl/htons/htonl)並不能正確讀取位域的值。

例如:

struct _exam_
{
  unsigned int tag : 6;
  unsigned int field1 : 3;
  unsigned int field2 : 7;
  unsigned int field3 : 11;
  unsigned int pad :  5;
}Exam;

 

其中,tag,field2,pad是字節內位域,field1和field3是跨字節位域。當這個結構體從某個大端序平台(例如MIPS,big-endian)通過網絡傳送到PC機(little-endian),在pc機上無論調用ntohl與否,直接通過Exam.field3語句都無法獲取正確的值。

 

解決方案:

(1)調用ntohl,並保存該變量為一個unsigned int。

此時Exam的5個成員將暫時按照地址從高到低的順序排列(正確的情況下,無論BE還是LE,結構體內部的成員都應當按照先後順序,從低地址到高地址排列)。

 unsigned int temp = 0;
 memcpy(&temp, sizeof(temp), &Exam);
 temp = ntohl(temp);  

 

(2)使用位運算符獲取位域正確值。

經過上一步驟,雖然Exam的成員(將temp內的碼流當作Exam)在內存中的排列順序是錯的,但我們將錯就錯。從日常印刷書寫的“邏輯視圖”角度看,Exam.tag在“最左端”(高位),Exam.pad在“最右端”(低位),且5個位域內的比特順序也是正確的。因此可以直接用移位運算符獲取其中的值。

struct _exam_ ExamWin32;
ExamWin32.tag = temp >> 26;   // 高位全部為0,不必使用位與運算
ExamWin32.field1 = (temp >> 23) & 0x00000007; // 只獲取移位操作結果的低3位。
ExamWin32.field2 =  (temp >> 16) & 0x0000007F; 
ExamWin32.field3 =  (temp >> 5) & 0x000007FF; 
ExamWin32.pad = temp & 0x0000001F;

 

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