C# 中的位域
我有一个需要填充并写入磁盘的结构(实际上是几个)。
一个例子是:
byte-6
bit0 - original_or_copy
bit1 - copyright
bit2 - data_alignment_indicator
bit3 - PES_priority
bit4-bit5 - PES_scrambling control.
bit6-bit7 - reserved
在 CI 中可能会执行如下操作:
struct PESHeader {
unsigned reserved:2;
unsigned scrambling_control:2;
unsigned priority:1;
unsigned data_alignment_indicator:1;
unsigned copyright:1;
unsigned original_or_copy:1;
};
在 C# 中是否有任何方法可以执行此操作,使我能够使用结构解引用点运算符访问这些位?
对于几个结构,我可以只在访问器函数中进行位移。
我有大量的结构需要以这种方式处理,所以我正在寻找更容易阅读和更快编写的东西。
I have a structure which I need to populate and write to disk (several actually).
An example is:
byte-6
bit0 - original_or_copy
bit1 - copyright
bit2 - data_alignment_indicator
bit3 - PES_priority
bit4-bit5 - PES_scrambling control.
bit6-bit7 - reserved
In C I might do something like the following:
struct PESHeader {
unsigned reserved:2;
unsigned scrambling_control:2;
unsigned priority:1;
unsigned data_alignment_indicator:1;
unsigned copyright:1;
unsigned original_or_copy:1;
};
Is there any way to do this in C# that would enable me to access the bits using the struct dereferencing dot operator?
For a couple of structures, I can just do bit shifting wrapped in an accessor function.
I have loads of structures to handle in this way, so I'm looking for something that's easier to read and quicker to write.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
今天早上我用 T4 写了一篇。 :) 与 Zbyl 相同的例子,尽管我加入了一些 uint 大小调整的乐趣。 这只是第一遍,显然可以使用一些错误检查。 此外,bitFields 规范数组在单独的文件中会更好,可能是 .ttinclude 或 json/yaml..
I wrote one this morning with T4. :) Same example as Zbyl, though I threw in a bit of uint sizing fun. This is just a first pass, it could obviously use a little error checking. Also the bitFields spec array would be nicer in a separate file, maybe a .ttinclude, or a json/yaml..
我写了一篇,分享一下,可能会对某人有所帮助:
以及用法:
I wrote one, share it, may help someone:
and the usage:
我认为,如果将其设为字节枚举,标志枚举也可以工作:
A flags enum can work too, I think, if you make it a byte enum:
带有 Flags 属性的枚举可能有帮助吗? 请参阅此处:
C# 中的 [Flags] 枚举属性意味着什么?
Could an Enum with the Flags Attribute help maybe? See here:
What does the [Flags] Enum Attribute mean in C#?
虽然它是一个类,但使用 BitArray 似乎是最少重新发明轮子的方法。 除非您确实对性能有迫切要求,否则这是最简单的选择。 (可以使用
[]
运算符引用索引。)While it is a class, using
BitArray
seems like the way to least reinvent the wheel. Unless you're really pressed for performance, this is the simplest option. (Indexes can be referenced with the[]
operator.)我发现自己对这些辅助函数非常满意:
然后:
I find myself quite comfortable with these helper functions:
then:
您还可以使用
BitVector32
,尤其是节结构
。 这个例子非常好。You could also use the
BitVector32
and especially theSection struct
. The example is very good.另一种基于 Zbyl 的回答。 这个对我来说更容易改变 - 我只需要调整 sz0,sz1... 并且确保 Set/Get 块中的 mask# 和 loc# 是正确的。
就性能而言,它应该是相同的,因为它们都解析为 38 个 MSIL 语句。 (常量在编译时解析)
One more based off of Zbyl's answer. This one is a little easier to change around for me - I just have to adjust the sz0,sz1... and also make sure mask# and loc# are correct in the Set/Get blocks.
Performance wise, it should be the same as they both resolved to 38 MSIL statements. (constants are resolved at compile time)
正如 Christophe Lambrechts 所建议的那样,BitVector32 提供了一个解决方案。 抖动性能应该足够,但不确定。
下面是说明此解决方案的代码:
您可以通过这种方式做很多事情。 通过为每个字段提供手工访问器,您可以在不使用 BitVector32 的情况下做得更好:
令人惊讶的是,最后一个手工解决方案似乎是最方便、最不复杂且最短的解决方案。 这当然只是我个人的喜好。
As Christophe Lambrechts suggested BitVector32 provides a solution. Jitted performance should be adequate, but don't know for sure.
Here's the code illustrating this solution:
You can do a lot this way. You can do even better without using BitVector32, by providing handmade accessors for every field:
Surprisingly this last, handmade solution seems to be the most convenient, least convoluted, and the shortest one. That's of course only my personal preference.
您想要 StructLayoutAttribute
这个实际上是一个联合,但您可以将其用作位字段 - 您只需知道每个字段的位在字节中的位置即可。 AND 的实用函数和/或常量会有所帮助。
还有 LayoutKind.Sequential 允许您以 C 方式执行此操作。
You want StructLayoutAttribute
This is really a union but you can use it as a bitfield--you just have to be conscious of where in the byte the bits for each field are supposed to be. Utility functions and/or constants to AND against can help.
There is also LayoutKind.Sequential which will allow you to do it the C way.
通过使用枚举,您可以做到这一点,但看起来很尴尬。
By using an enum you can do this, but will look awkward.
我可能会使用属性将一些东西组合在一起,然后使用转换类将适当的属性结构转换为位域基元。 像...
这样的东西会产生预期的...000101011。 当然,它需要更多的错误检查和稍微理智的打字,但这个概念(我认为)是合理的,可重用的,并且可以让你敲出易于维护的结构。
阿达姆
I'd probably knock together something using attributes, then a conversion class to convert suitably attributed structures to the bitfield primitives. Something like...
Which produces the expected ...000101011. Of course, it needs more error checking and a slightly saner typing, but the concept is (I think) sound, reusable, and lets you knock out easily maintained structures by the dozen.
adamw