我昨天花了大部分时间试图解决这个问题,作为“使用 c# 的 StrucLayout 和 FieldOffset 表示联合位域”问题的一个更大的部分,这不仅会回答你的问题(上图),而且可以在这里找到:
Representing union bitfields using c#'s StrucLayout and FieldOffset
本质上,您需要定义一个结构(值类型)并使用 BitVector32 对象为您希望表示的每个位域定义位域部分。您可以跳过关于工会的部分,因为这与您的问题无关,但大部分帖子仍然与您的问题有关。
只是为了好玩,我想我会为您的 RGB16 示例创建 C# 结构:
注意:BitVector32 对象的长度为 32 位,因此名称上的“16”有点误导...请注意这一点
[StructLayout(LayoutKind.Explicit, Size = 1, CharSet = CharSet.Ansi)]
public struct Rgb16
{
#region Lifetime
/// <summary>
/// Ctor
/// </summary>
/// <param name="foo"></param>
public Rgb16(int foo)
{
// allocate the bitfield
buffer = new BitVector32(0);
// initialize bitfield sections
r = BitVector32.CreateSection(0x0f); // 4
g = BitVector32.CreateSection(0x1f, r); // 5
b = BitVector32.CreateSection(0x0f, g); // 4
}
#endregion
#region Bifield
// Creates and initializes a BitVector32.
[FieldOffset(0)]
private BitVector32 buffer;
#endregion
#region Bitfield sections
/// <summary>
/// Section - Red
/// </summary>
private static BitVector32.Section r;
/// <summary>
/// Section - Green
/// </summary>
private static BitVector32.Section g;
/// <summary>
/// Section - Blue
/// </summary>
private static BitVector32.Section b;
#endregion
#region Properties
/// <summary>
/// Flag 1
/// </summary>
public byte R
{
get { return (byte)buffer[r]; }
set { buffer[r] = value; }
}
/// <summary>
/// Flag 2
/// </summary>
public byte G
{
get { return (byte)buffer[g]; }
set { buffer[g] = value; }
}
/// <summary>
/// Flag 1
/// </summary>
public byte B
{
get { return (byte)buffer[b]; }
set { buffer[b] = value; }
}
#endregion
#region ToString
/// <summary>
/// Allows us to represent this in human readable form
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"Name: {nameof(Rgb16)}{Environment.NewLine}Red: {R}: Green: {G} Blue: {B} {Environment.NewLine}BitVector32: {buffer}{Environment.NewLine}";
}
#endregion
}
要使用它,您将分配如下:
internal static class Program
{
/// <summary>
/// Main entry point
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
var rgb16 = new Rgb16(0)
{
R = 24,
G = 16,
B = 42
};
另外,请注意这里有一个参考:
Bit fields in C#
这里还有许多其他答案,但它们有许多需要注意的陷阱。也许我在这里能做的最好的事情就是列出您可能想要查找的内容:
- 确保将数据打包在字节边界上
- 确保指定数据类型的大小,即 int 会根据硬件改变大小,System.Int32 不会。
- 确保遵守整数数据类型的“字节顺序”
- 尽可能避免与底层语言有任何联系,即避免使用语言内存管理器——坚持“普通旧数据类型”。这将使通过网络传输数据变得更加简单。