我正在查看名为C#的BitStream库,它允许您向标准的C# Stream对象写入和读取任意数量的位。我注意到在我看来,一个奇怪的设计决定:
当向空字节添加位时,这些位被添加到字节的MSB中。例如:
var s = new BitStream();
s.Write(true);
Debug.Assert(s.ToByteArray()[0] == 0x80); // and not 0x01
var s = new BitStream();
s.Write(0x7,0,4);
s.Write(0x3,0,4);
Debug.Assert(s.ToByteArray()[0] == 0x73); // and not 0x37但是,当将数字中的位作为输入时,输入编号的第一位是LSB。例如
//s.Write(int input,int bit_offset, int count_bits)
//when referencing the LSB and the next bit we'll write
s.Write(data,0,2); //and not s.Write(data,data_bits_number,data_bits_number-2)在我看来似乎不一致。因为在这种情况下,当“逐步”复制一个字节时,就像前面的例子(前四位,然后最后四位)一样,我们将不会得到原来的字节。我们需要“向后”复制它(首先是最后四位,然后是前四位)。
我错过了那个设计有什么原因吗?与此行为相关的位流的其他实现吗?这方面的设计考虑是什么?
看来,ffmpeg比特流的行为方式我认为是一致的。在使用OR中的src指针在函数中移动字节之前,看看它移动字节的数量。
作为附带说明:
添加的第一个字节是字节数组中的第一个字节。例如
var s = new BitStream();
s.Write(0x1,0,4);
s.Write(0x2,0,4);
s.Write(0x3,0,4);
Debug.Assert(s.ToByteArray()[0] == 0x12); // and not s.ToByteArray()[1] == 0x12发布于 2010-02-22 22:17:40
以下是一些额外的注意事项:
在布尔值的情况下,只需要一个位来表示真或假。当该位被添加到流的开头时,比特流是“1”。当您将该流扩展到字节长度时,它强制将零位填充到流的末尾,即使这些比特一开始并不存在于流中。流中的位置与位的值一样重要,而"1000000“或0x80的比特流保证了这样的期望,即流的后续读取器可能有他们读取的第一个位是添加的第一个位。
第二,像整数这样的其他数据类型需要更多的位来表示,所以它们在流中所占的空间要比布尔人多。当不同大小的数据类型在字节边界上不对齐时,在同一流中混合可能会非常困难。
最后,如果您在英特尔x86上,您的CPU体系结构是“小终端”,这意味着LSB首先要像您所描述的那样。如果您需要将值作为大端存储在流中,则需要在代码中添加一个转换层,类似于上面所示,您一次按您想要的顺序将一个字节放入流中。这很烦人,但如果您需要与大端Unix盒进行互操作,或者按协议规范的要求进行互操作,则通常需要这样做。
希望这能帮上忙!
发布于 2009-09-10 18:13:55
我错过了那个设计有什么原因吗?与此行为相关的位流的其他实现吗?这方面的设计考虑是什么?
我怀疑这种割礼背后有什么重大意义。从技术上讲,只要作者和读者在顺序上达成一致,这就无关紧要了。
发布于 2010-03-25 11:51:41
我同意Elazar的观点。
正如他/她指出的那样,在这种情况下,读者和作家对位顺序不一致。事实上,它们是不相容的。
https://stackoverflow.com/questions/1391984
复制相似问题