为了账号安全,请及时绑定邮箱和手机立即绑定

C#中的位字段

C#中的位字段

C#
慕村9548890 2019-10-08 10:53:21
我有一个需要填充并写入磁盘的结构(实际上有几个)。一个例子是: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#中执行此操作,从而使我能够使用结构取消引用点运算符访问这些位?对于两个结构,我只需要包装访问器函数中的位移即可。我有大量的结构要以这种方式处理,因此我正在寻找更易于阅读和编写的东西。
查看完整描述

3 回答

?
拉莫斯之舞

TA贡献1820条经验 获得超10个赞

我可能会使用属性将某些东西组合在一起,然后使用一个转换类将适当地归因于结构的结构转换为位域基元。就像是...


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。当然,它需要更多的错误检查和更精巧的键入,但是(我认为)该概念是合理的,可重用的,并且可以让您轻松打出一打维护的结构。

查看完整回答
反对 回复 2019-10-08
?
红颜莎娜

TA贡献1842条经验 获得超12个赞

通过使用枚举,您可以执行此操作,但是看起来很尴尬。


[Flags]

public enum PESHeaderFlags

{

    IsCopy = 1, // implied that if not present, then it is an original

    IsCopyrighted = 2,

    IsDataAligned = 4,

    Priority = 8,

    ScramblingControlType1 = 0,

    ScramblingControlType2 = 16,

    ScramblingControlType3 = 32,

    ScramblingControlType4 = 16+32,

    ScramblingControlFlags = ScramblingControlType1 | ScramblingControlType2 | ... ype4

    etc.

}


查看完整回答
反对 回复 2019-10-08
?
千巷猫影

TA贡献1829条经验 获得超7个赞

您想要StructLayoutAttribute


[StructLayout(LayoutKind.Explicit, Size=1, CharSet=CharSet.Ansi)]

public struct Foo 

{ [FieldOffset(0)]public byte original_or_copy; 

  [FieldOffset(0)]public byte copyright;

  [FieldOffset(0)]public byte data_alignment_indicator; 

  [FieldOffset(0)]public byte PES_priority; 

  [FieldOffset(0)]public byte PES_scrambling_control; 

  [FieldOffset(0)]public byte reserved; 

}

这实际上是一个并集,但您可以将其用作位域-您只需要知道每个字段的位应该在字节中的哪个位置即可。实用程序函数和/或与AND相对的常量会有所帮助。


const byte _original_or_copy = 1;

const byte _copyright        = 2;


//bool ooo = foo.original_or_copy();

static bool original_or_copy(this Foo foo) 

{ return  (foo.original_or_copy & _original_or_copy)  == original_or_copy;

}    

还有LayoutKind.Sequential,它可以让您以C方式进行操作。


查看完整回答
反对 回复 2019-10-08
  • 3 回答
  • 0 关注
  • 481 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信