位字段结构列表

时间:2014-01-17 20:45:12

标签: c++ oop

我有以下bitfield结构:

struct DescriptorByte
{
    unsigned short IsImmedCalc : 1;
    unsigned short IsPrefix : 1;
    unsigned short NoMemOp : 1;
    unsigned short Size : 5;
};

我想创建一个用于保存许多DescriptorByte结构的表,所以我创建了这个:

struct OpcodeList
{
    DescriptorByte ADD_8_MO;
    DescriptorByte ADD_32_MO;
    DescriptorByte ADD_8_OM;
    DescriptorByte ADD_32_OM;
    DescriptorByte ADD_8_OI = { TRUE, FALSE, TRUE, 1 + 1 };
    DescriptorByte ADD_32_OI = { TRUE, FALSE, TRUE, 1 + 4 };
    DescriptorByte PUSH_ES = { TRUE, FALSE, TRUE, 1 };
};

这是否与每个成员长度为1个字节的结构相同?此外,我希望能够像这样引用初始化成员:

DescriptorByte ADD_8_OI = { IsImmedCalc = true, Size = 1 };

但是视觉工作室不让我。所有这一切背后的想法是有一个DescriptorByte表,这是最好的方法吗?还有什么是最好的初始化方法?感谢。

2 个答案:

答案 0 :(得分:2)

  1. “这与具有每个成员长度为1个字节的结构相同吗?”

    如果您不使用#pragma pack或类似的东西,您的编译器可能会添加填充。

    但是在这个特定情况下没有任何填充,所以基本上答案是肯定的。

    只需将unsigned short更改为unsigned char,每个成员的长度为1个字节。

  2. 添加'。'在每个字段的左侧:

    DescriptorByte ADD_8_OI = { .IsImmedCalc = true, .Size = 1 };

    或者,只需按正确的顺序写下实际值(缺少的值将设置为0):

    DescriptorByte ADD_8_OI = { true, 1 };

答案 1 :(得分:1)

编辑:发布此认为这是一个C#问题,抱歉!把它留给别人。

C#不支持位字段。但是,您仍然可以使用适当大小的单个成员变量以及各种getter属性来“模拟”该行为。

在您的示例中,您希望使用无符号的8位整数值(byte)并封装这些位域。不用担心,您仍然可以使用struct来完成所有这些操作,以便更轻松地进行编组和互操作。

所以,让我们带你的DescriptorByte并重新创建你想要做的事情:

struct DescriptorByte
{
    static readonly byte IsImmedCalcFlag = 0x80;    // 1000 0000
    static readonly byte IsPrefixFlag = 0x40;       // 0100 0000
    static readonly byte NoMemOpFlag = 0x20;        // 0010 0000
    static readonly byte FlagsBitMask = 0xE0;       // 1110 0000
    static readonly byte SizeBitMask = 0x1F;        // 0001 1111

    byte field;

    public bool IsImmedCalc
    {
        get { return (field & IsImmedCalcFlag) > 0; }
        set
        {
            if (value)
                field = (byte)(field | IsImmedCalcFlag);   // Set the bit
            else
                field = (byte)(field & ~IsImmedCalcFlag);  // Clear the bit
        }
    }

    public bool IsPrefix
    {
        get { return (field & IsPrefixFlag) > 0; }
        set
        {
            if (value)
                field = (byte)(field | IsPrefixFlag);   // Set the bit
            else
                field = (byte)(field & ~IsPrefixFlag);  // Clear the bit
        }
    }

    public bool NoMemOp
    {
        get { return (field & NoMemOpFlag) > 0; }
        set
        {
            if (value)
                field = (byte)(field | NoMemOpFlag);    // Set the bit
            else
                field = (byte)(field & ~NoMemOpFlag);   // Clear the bit
        }
    }

    public byte Size
    {
        get { return (byte)(field & SizeBitMask); }
        set { field = (byte)((field & FlagsBitMask) | (value & SizeBitMask)); }
    }
}