我有一个需要填充并写入磁盘的结构(实际上有几个)。
一个例子是:
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#中执行此操作,从而使我能够使用结构取消引用点运算符访问这些位?
对于两个结构,我只需要包装访问器函数中的位移即可。
我有大量的结构要以这种方式处理,因此我正在寻找更易于阅读和编写的东西。
我可能会使用属性将某些东西组合在一起,然后是一个转换类,以将适当地归属的结构转换为位域基元。就像是…
using System; namespace BitfieldTest { [global::System.AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] sealed class BitfieldLengthAttribute : Attribute { uint length; public BitfieldLengthAttribute(uint length) { this.length = length; } public uint Length { get { return length; } } } static class PrimitiveConversion { public static long ToLong<T>(T t) where T : struct { long r = 0; int offset = 0; // For every field suitably attributed with a BitfieldLength foreach (System.Reflection.FieldInfo f in t.GetType().GetFields()) { object[] attrs = f.GetCustomAttributes(typeof(BitfieldLengthAttribute), false); if (attrs.Length == 1) { uint fieldLength = ((BitfieldLengthAttribute)attrs[0]).Length; // Calculate a bitmask of the desired length long mask = 0; for (int i = 0; i < fieldLength; i++) mask |= 1 << i; r |= ((UInt32)f.GetValue(t) & mask) << offset; offset += (int)fieldLength; } } return r; } } struct PESHeader { [BitfieldLength(2)] public uint reserved; [BitfieldLength(2)] public uint scrambling_control; [BitfieldLength(1)] public uint priority; [BitfieldLength(1)] public uint data_alignment_indicator; [BitfieldLength(1)] public uint copyright; [BitfieldLength(1)] public uint original_or_copy; }; public class MainClass { public static void Main(string[] args) { PESHeader p = new PESHeader(); p.reserved = 3; p.scrambling_control = 2; p.data_alignment_indicator = 1; long l = PrimitiveConversion.ToLong(p); for (int i = 63; i >= 0; i--) { Console.Write( ((l & (1l << i)) > 0) ? "1" : "0"); } Console.WriteLine(); return; } } }
产生预期的… 000101011。当然,它需要更多的错误检查和更合理的键入,但是(我认为)该概念是合理的,可重用的,并且使您可以轻松地将十几个结构进行维护。
亚当