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 是一个不错的起点。