首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >C#中的位字段

C#中的位字段
EN

Stack Overflow用户
提问于 2008-08-18 11:19:28
回答 12查看 107.2K关注 0票数 83

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

下面是一个例子:

代码语言:javascript
复制
byte-6    
bit0 - original_or_copy  
bit1 - copyright  
bit2 - data_alignment_indicator  
bit3 - PES_priority  
bit4-bit5 - PES_scrambling control.  
bit6-bit7 - reserved  

在C语言中,我可能会做类似以下的事情:

代码语言:javascript
复制
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#中使用结构解引用点运算符来访问这些位?

对于几个结构,我只需要在一个存取器函数中进行位移位。

我有大量的结构要以这种方式处理,所以我正在寻找更容易阅读和更快编写的东西。

EN

回答 12

Stack Overflow用户

回答已采纳

发布于 2008-08-18 13:31:31

我可能会拼凑一些使用属性的东西,然后是一个转换类,将适当的属性结构转换为位域原语。就像..。

代码语言:javascript
复制
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。当然,它需要更多的错误检查和稍微清醒的类型,但它的概念(我认为)是健全的,可重用的,并且可以让你敲出十几个容易维护的结构。

adamw

票数 57
EN

Stack Overflow用户

发布于 2008-08-18 12:25:52

通过使用枚举,您可以做到这一点,但看起来会很笨拙。

代码语言:javascript
复制
[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.
}
票数 26
EN

Stack Overflow用户

发布于 2008-08-18 11:32:53

你想要StructLayoutAttribute

代码语言:javascript
复制
[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; 
}

这实际上是一个联合,但您可以将其用作位字段--您只需意识到每个字段的位应该在字节中的什么位置。实用函数和/或常量可以提供帮助。

代码语言:javascript
复制
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语言来做。

票数 22
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14464

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档