1

我有以下情况:

struct object1  {

    bool a:1;
    bool b:1;
    uint8_t c:2;
    bool d:1;
    abc  e:3;

    uint16_t header;
    uint8_t footer;
    uint8_t mid[4];
}

我可能不知道语法,但在 C# 中玩位并不像 C++ 那样简单。我已经使用 BitArray 和 BitConverter 类来制作填充数据的方法,但我遇到了问题:

object1 * rqr = (object1  *) &Msg.Data[2];

基本上,他们将对象转换为字节数组。我所做的每一次搜索都在尖叫序列化,但要真正转换上面的行,我不能有任何额外的元数据或任何东西。

我真的很想创建一个指向内存位置的指针并将该位置“投射”到所述对象。这可能吗?如果没有,是否有解决此问题的方法?我无法想象这个级别的位操作被完全排除在外。在假设之前,我会默认我只是不知道。

编辑:: 我知道 C# 不允许指向管理类型的指针。我要问的是是否有办法说:

Byte[] ayData = new Byte[8];
ObjectOfSize8 nObject =  (ObjectOfSize8)ayData;

我知道上面的方法行不通,但是,如果你足够聪明地理解对象的内存大小,语言中是否有允许数据转换的东西?

4

2 回答 2

2

您可以使用为您处理位移和掩码的结构来解决位域问题:

[StructLayout(LayoutKind.Sequential, Size=1)]
public struct BitField8
{
    private byte _bits;

    private static readonly byte[] Masks = new byte[] { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
    public BitField8(int val)
    {
        _bits = (byte) val;
    }

    public byte Get(int bit, int length = 1)
    {
        int shift = bit + length - 1;
        return (byte) ((_bits >> shift) & Masks[length-1]);
    }

    public void Set(int bit, int length, int val)
    {
        int mask = Masks[length-1];
        int shift = bit + length - 1;
        val = (val & mask) << shift;
        mask = ~(mask << shift);
        _bits = (byte)((_bits & mask) | val);
    }
}

所以在你的例子中:

bool a:1;
bool b:1;
uint8_t c:2;
bool d:1;
abc  e:3;

您可以a通过调用来设置Set(0, 1, 1)(将 a 设置为 1)。

要给出c3 的值,您可以调用Set(3, 2, 3). (c占用位 2 和 3)。

这基本上复制了 C++ 位域的功能,尽管我承认我的位顺序可能有误。我真的不知道 C++ 编译器是放在a第 0 位还是第 7 位。

您可以对 16 位、32 位和 64 位位域执行类似的操作。

所以你的结构将包含:

BitField8 myBitfield;
于 2013-08-05T22:27:58.643 回答
1

你不能用 C# 中的类型转换来做你所要求的。我怀疑做你需要的最干净的方法可能是固定 C# 结构。然后你有一个 IntPtr 可以与 Marshal.Copy 一起使用来复制到字节数组和从字节数组复制。

至于位域,需要使用按位移位、按位或和按位与操作来管理它们。

于 2013-08-05T22:23:02.883 回答