C# - 位和字节
C# - Bits and Bytes
我尝试用两个字节 (byte[2]) 存储一些信息。
在第一个字节的前四位中,我想存储一个 "type-information" 编码为 0-9 的值。在最后四位+第二个字节中我想存储一个size-info,所以size-info的最大值是4095(0xFFF);
让我们举一些例子来解释我的意思。
当类型信息为 5 且大小为 963 时,结果应如下所示:35-C3 作为十六进制字符串。
35-C3 => 5 是类型信息,3C3 是 963。
03-00 => 类型信息 3 和大小 0。
13-00 => 类型信息 3 和尺寸 1。
但我不知道如何使用 C# 执行此操作并需要一些社区帮助:
byte type = 5; // hex 5
short size = 963; // hex 3C3
byte[] bytes = ???
string result = BitConverter.ToString(bytes);
// here result should by 35-C3
它应该是这样的:
bytes = new byte[2];
bytes[0] = type << 4 | size >> 8;
bytes[1] = size & 0xff;
注意:最初我的数字是错误的,我写了 type << 8 | size >> 16
而它应该是 type << 4 | size >> 8
正如 Aleksey 在他的回答中显示的那样。
评论已移至后代答案中:
通过在将 type
位存储到 bytes[0]
之前将它们向左移动 4 位,您可以确保它们占据 bytes[0]
的前 4 位。通过将您的 size
位向右移动 8 位,您可以确保大小的低 8 位被丢弃,并且只保留前 4 位,并且这些前 4 位将被存储到低 4 位中bytes[0]
个。帮忙画个图:
bytes[0] bytes[1]
+------------------------+ +------------------------+
| 7 6 5 4 3 2 1 0 | | 7 6 5 4 3 2 1 0 |
+------------------------+ +------------------------+
type << 4
+-----------+
| 3 2 1 0| <-- type
+-----------+
+------------+ +------------------------+
|11 10 9 8 | | 7 6 5 4 3 2 1 0 | <-- size
+------------+ +------------------------+
size >> 8 size & 0xff
size
是一个 12 位的量。这些位位于位置 11 到 0。通过将其右移 8,您将删除最右边的 8 位,并且只剩下前 4 位,位于位置 3-0。然后将这4位存入bytes[0]
.
的低4位
试试这个:
byte[] bytes = new byte[2];
bytes[0] = (byte) (type << 4 | size >> 8);
bytes[1] = (byte) (size & 0xff);
类型的内存配置文件的微优化不是您通常应该在 .NET 中打扰的事情。如果您是 运行 本机 C++,我可以在某种程度上理解这一点,但我仍然建议您不要这样做。这是很多工作,但收益有限。
但在 .NET 中,您只需创建一个 class 或带有枚举 (Int8) "Type" 和 Int16 SizeInfo 的结构,比如 "good enough" 就可以了。将你的资源花在更好的事情上,然后从它那里削减 1 字节的内存,而 64 位是当今大多数计算机的本机整数大小。
BitArray 是最接近实际从 .NET 中的字节定义特定位的方法。它提供了一些关于类似类型的信息。
如果您想以困难的方式进行数学运算,Modulo 是一个不错的起点。
我尝试用两个字节 (byte[2]) 存储一些信息。
在第一个字节的前四位中,我想存储一个 "type-information" 编码为 0-9 的值。在最后四位+第二个字节中我想存储一个size-info,所以size-info的最大值是4095(0xFFF);
让我们举一些例子来解释我的意思。 当类型信息为 5 且大小为 963 时,结果应如下所示:35-C3 作为十六进制字符串。
35-C3 => 5 是类型信息,3C3 是 963。
03-00 => 类型信息 3 和大小 0。
13-00 => 类型信息 3 和尺寸 1。
但我不知道如何使用 C# 执行此操作并需要一些社区帮助:
byte type = 5; // hex 5
short size = 963; // hex 3C3
byte[] bytes = ???
string result = BitConverter.ToString(bytes);
// here result should by 35-C3
它应该是这样的:
bytes = new byte[2];
bytes[0] = type << 4 | size >> 8;
bytes[1] = size & 0xff;
注意:最初我的数字是错误的,我写了 type << 8 | size >> 16
而它应该是 type << 4 | size >> 8
正如 Aleksey 在他的回答中显示的那样。
评论已移至后代答案中:
通过在将 type
位存储到 bytes[0]
之前将它们向左移动 4 位,您可以确保它们占据 bytes[0]
的前 4 位。通过将您的 size
位向右移动 8 位,您可以确保大小的低 8 位被丢弃,并且只保留前 4 位,并且这些前 4 位将被存储到低 4 位中bytes[0]
个。帮忙画个图:
bytes[0] bytes[1]
+------------------------+ +------------------------+
| 7 6 5 4 3 2 1 0 | | 7 6 5 4 3 2 1 0 |
+------------------------+ +------------------------+
type << 4
+-----------+
| 3 2 1 0| <-- type
+-----------+
+------------+ +------------------------+
|11 10 9 8 | | 7 6 5 4 3 2 1 0 | <-- size
+------------+ +------------------------+
size >> 8 size & 0xff
size
是一个 12 位的量。这些位位于位置 11 到 0。通过将其右移 8,您将删除最右边的 8 位,并且只剩下前 4 位,位于位置 3-0。然后将这4位存入bytes[0]
.
试试这个:
byte[] bytes = new byte[2];
bytes[0] = (byte) (type << 4 | size >> 8);
bytes[1] = (byte) (size & 0xff);
类型的内存配置文件的微优化不是您通常应该在 .NET 中打扰的事情。如果您是 运行 本机 C++,我可以在某种程度上理解这一点,但我仍然建议您不要这样做。这是很多工作,但收益有限。
但在 .NET 中,您只需创建一个 class 或带有枚举 (Int8) "Type" 和 Int16 SizeInfo 的结构,比如 "good enough" 就可以了。将你的资源花在更好的事情上,然后从它那里削减 1 字节的内存,而 64 位是当今大多数计算机的本机整数大小。
BitArray 是最接近实际从 .NET 中的字节定义特定位的方法。它提供了一些关于类似类型的信息。
如果您想以困难的方式进行数学运算,Modulo 是一个不错的起点。