c# - C# 中的位域

标签 c# bit-fields

我有一个结构需要填充并写入磁盘(实际上是几个)。

一个例子是:

byte-6    
bit0 - original_or_copy  
bit1 - copyright  
bit2 - data_alignment_indicator  
bit3 - PES_priority  
bit4-bit5 - PES_scrambling control.  
bit6-bit7 - reserved  

在 C 中我可能会做如下的事情:

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。当然,它需要更多的错误检查和稍微更理智的打字,但这个概念(我认为)是合理的、可重用的,并且可以让你敲出许多易于维护的结构。

亚当

关于c# - C# 中的位域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46294984/

相关文章:

c++ - C/C++ 位域字节顺序在实际实践中真的是一个问题吗?

c# - 如何阻止其他域指向我的域?

c# - 会计数据库模式

c# - 用于验证数学方程式的正则表达式

c# - 在共享数据结构上同步

objective-c - 你能用位域从 C 结构创建 NSValue 吗?

c++ - 是否应该不鼓励使用 int 类型的位域?

sql-server - Microsoft 可以将三值字段存储在一个位中吗?

c# - Unity3d 2019.3.10 UnityEngine.UI;未找到

c++ - 需要元编程魔术来以无错误的方式定义位字段的母矿脉