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位的操作可以不写。