5

我的意思是,假设我有一个struct来表示一些数据,它看起来像这样:

struct LilStruct
{
    public readonly short A;
    public readonly byte B;
    public readonly byte C;

    public LilStruct(short a, byte b, byte c)
    {
        A = a;
        B = b;
        C = c;
    }
}

Ashort和两个byte值都可以放入 32 位。我想知道的是(出于对齐目的、性能等),是否以以下格式存储这些数据实际上是有意义的:

struct LilStruct
{
    private readonly uint _value;

    public LilStruct(short a, byte b, byte c)
    {
        _value = ((uint)a << 16) | ((uint)b << 8) | (uint)c;
    }

    public int A
    {
        get { return (int)(_value >> 16); }
    }

    public int B
    {
        get { return (int)(_value >> 8) & 0x000000FF; }
    }

    public int C
    {
        get { return (int)(_value & 0x000000FF); }
    }
}

这是没有意义的吗?有什么好处/缺点?

4

5 回答 5

3

在 .NET 中,当你要使用 a 时struct,你也可以像这样装饰结构StructLayoutAttribute

[StructLayout(LayoutKind.Sequential, Pack=1)]
struct LilStruct
{
    public readonly short A;
    public readonly byte B;
    public readonly byte C;

    public LilStruct(short a, byte b, byte c)
    {
        A = a;
        B = b;
        C = c;
    }
}

这将产生按顺序排列字段的效果,例如字段B将从偏移量 16 开始。

值为 1Pack表示字段在byte边界处对齐。

于 2010-08-27T19:44:51.417 回答
2

如果值彼此紧密相关,通常一起传递,并且从不或很少相互独立修改,您应该只考虑将多个值填充到一个 uint 中。与单独存储三个字节相比,为修改其值而对 uint 进行解包和重新打包的成本使得这非常昂贵(在代码大小和执行时间方面)。

当在一个总共有 10k 字节 RAM 的微型设备上执行时,这样的打包可能是值得的,因为内存比执行速度更宝贵。在普通的台式电脑甚至手机设备上,这种包装可能不值得。

于 2010-08-27T19:54:34.120 回答
1

您可以保留您的结构定义,并应用StructLayoutAttribute.Pack值为 1 的StructLayout属性。但实际上,您可能会以访问速度为代价节省一点内存,因为这样数据不会以最有效的访问方式排列在内存中。编译器通常会以一种高效访问的方式布置内存,并且不会自动破坏太多内存。

与您提出的位移方法相比,这种方法至少可以使您的代码更易于理解(实际上可能与机器代码编译器从字节码生成的内容相似,也可能不相似)。

于 2010-08-27T19:59:42.450 回答
0

您将遇到的是内存中数据对象的大小和处理成本之间的简单权衡。如果内存是一个真正的问题,那么在您的机器上投入更多的 RAM 可能会更便宜。

于 2010-08-27T19:50:51.893 回答
0

在某些情况下,值得将东西塞进一个整数中。单独的存储空间通常不是一个好的理由,但如果将这些值一起用作字典的键,那么字典(整数,随便)将比字典(一些结构,随便)快得多。

于 2010-08-27T21:14:33.300 回答