C# 字節(數組)\16\32\64…位數據與位之間的計算
運算符介紹
運算名稱 | 運算符號 |
---|---|
左移 | << |
右移 | >> |
與 | & |
或 | | |
非 | ^ |
截取數據
例如:
UInt32 mini = 0x000ED0FF;
UInt16 low16 = (UInt16)(mini & 0xFFFF);
UInt16 hight16 = (UInt16)((mini>>16) & 0xFFFF);
byte low16lowByte = (byte)(mini & 0xFF);
byte low16HighByte = (byte)((mini >> 8) & 0xFF);
byte high16lowByte = (byte)(mini>>16 & 0xFF);
byte high16HighByte = (byte)((mini >> 24) & 0xFF);
擴展總結:
截取數據時,從數據源中的x位(計數從0開始)開始,連續截取y位。
公式爲:
目標數據類型 result =(強轉爲目標類型)((數據源>>x)&yHex)
注:yHex表示將y個1(2進制)轉換成16進制
例如:從一個32位無符號數據:0x000ED0FF中的第2位開始,截取11位的數據爲:
UInt16 res = (UInt16)((mini >> 2) & 0x07FF);
拼裝數據
在實際應用開發過程中,我們需要解析和拼裝數據,拼裝數據多數情況下是將不規則的數據組裝成規整的字節數組。下面我們研究下如何將多個信息拼裝到某一個字節或者多個連續字節中。
將下面三個數據拼裝到單個字節中。
byte a ,byte b , byte c。
其組裝到目標字節的結構如下表所示:
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
a | a | a | a | - | b | - | c |
a佔用高4位,b佔用第2位,c佔用第0位
示例代碼如下所示:
// 1.獲取待拼接數據
byte a = 0x09;
byte b = 0x01;
byte c = 0x01;
// 2.將拼接數據按位切分(保證數據完整性,防止溢出),然後移動到目標位
byte hh = (byte)((a & 0x0F) << 4);
byte mm = (byte)((b & 0x01) << 2);
byte ll = (byte)((c & 0x01) << 0);
// 3.通過或運算“|”拼接
byte result = (byte)(hh | mm | a | ll);
拼接過程如上面代碼,很清晰地進行了闡述。
強調一點:在第2步中,與運算“&”目的是爲了規整數據【保證其結果最大不過後面與上的值】,保證後面在做與運算時,拼接數據的準確性。
整理公式:
目標類型 result =(強轉爲目標類型)( ((a1 & Ha1) <<Ca1) | ((a2 & Ha2) <<Ca2) | … | ((an & Han) <<Can) )
其中:
a1=第一個數據;
HCa1=第一個數據在目標數據中佔位數個1的16進制數;
Ca1=第一個數據在目標數據中的最低位的座標標記;
a2=第二個數據;
HCa2=第二個數據在目標數據中佔位數個1的16進制數;
Ca2=第二個數據在目標數據中的最低位的座標標記;
…
an=第n個數據;
HCan=第n個數據在目標數據中佔位數個1的16進制數;
Can=第n個數據在目標數據中的最低位的座標標記;
應用:
將下面四個數據,分別保存到一個包含兩個字節的字節數組中。其格式如下所示
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|
0 | - | a | a | b | c | c | c | c |
1 | c | c | c | c | c | c | c | d |
示例代碼:
byte a = 0x00;
byte b = 0x01;
UInt16 c = 0x0921;
byte d = 0x01;
byte[] result = { 0x00, 0x00 };
// 取全部數據 並移動到第一個字節【高】的對應位置
UInt16 aa = (UInt16)((a & 0x03) << 5);
UInt16 bb = (UInt16)((b & 0x01) << 4);
// 取c的高4位[從第7位開始,取4位],第一個字節尾部,不做移動
UInt16 hc = (UInt16)((c >> 7) & 0x0F);
// 取c的低7位,並左移1位,並移動到第二個字節【低】的對應位置
UInt16 lc = (UInt16)((c & 0x7F) << 1);
// 取d的全部數據(1位),第二個字節尾部,不做移動
UInt16 dd = (UInt16)((d & 0x01) << 0);
// 【高】字節
result[0] = (byte)(aa | bb | hc);
// 【低】字節
result[1] = (byte)(lc | dd);
注意:在拆分c變量時,截取數據一定要準確。如果左移或者右移0位的操作可以不寫。