如果我有三个单独的值,它们都可以容纳 32 位,那么使用 uint 来存储它们是否有意义?

发布于 2024-09-16 10:53:51 字数 898 浏览 6 评论 0原文

我的意思是,假设我有一个 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;
    }
}

一个 short 和两个 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); }
    }
}

这毫无意义吗?有什么好处/缺点?

What I mean is, say I have a struct to represent some data and it looks like this:

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;
    }
}

A short and two byte values could all fit into 32 bits. What I'm wondering is (for alignment purposes, performance, whatever) if it would actually make sense to store this data in the following format instead:

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); }
    }
}

Is this pointless? What would be the benefits/drawbacks?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

却一份温柔 2024-09-23 10:53:51

在 .NET 中,当您无论如何都要使用 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 开始。

Pack 表示字段在字节边界对齐。

In .NET, when you are going to use a struct anyway, you can as well decorate the struct with StructLayoutAttribute like this:

[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;
    }
}

This will have the effect that the fields are laid out sequentially, e.g. field B will start at offset 16.

A value of 1 for Pack means that the fields are aligned at the byte boundaries.

棒棒糖 2024-09-23 10:53:51

仅当这些值彼此紧密相关(通常一起传递)并且从不或很少相互独立修改时,才应考虑将多个值塞入一个 uint 中。与单独存储三个字节相比,解包和重新打包 uint 以修改其值的成本非常昂贵(在代码大小和执行时间方面)。

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

You should only consider cramming multiple values into a uint if the values are closely tied to each other, usually passed around together, and are never or very rarely modified independently of each other. The cost of unpacking and repacking the uint in order to modify its value makes this very expensive (in code size and execution time) compared to just storing three bytes separately.

When executing on a microdevice with a total of 10k bytes of RAM, packing like this might be worth it because memory is more precious than execution speed. On a normal desktop PC or even mobile phone device, this packing is probably not worth the effort.

空城仅有旧梦在 2024-09-23 10:53:51

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

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

You could stay with your struct definition, and apply the StructLayout attribute with an StructLayoutAttribute.Pack value of 1. But in fact, you will probably save a little bit of memory at the expense of access speed, as this way the data would not be laid out in memory in a way that is most efficient to access. The compiler normally would lay out the memory in a way that is efficient to access and would not spoil too much memory automatically.

This approach would at least keep your code more understandable than the bit shifting approach you proposed (which might or might not in fact still be similar to what the machine code compiler would generate from the byte code).

嘿看小鸭子会跑 2024-09-23 10:53:51

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

What you will encounter is a simple trade-off between the size of your in-memory data objects and the cost of processing. If memory is a real concern, it may simply be cheaper to throw more RAM at your machine.

待天淡蓝洁白时 2024-09-23 10:53:51

在某些情况下,将内容塞入整数是值得的。单独的存储空间通常不是一个很好的理由,但是如果这些值要一起用作例如字典的键,则字典(Integer,Whatever)将比字典(Of SomeStructure,Whatever)快得多。

There are a few cases when it's worthwhile to cram stuff into an integer. Storage space alone is usually not a good reason, but if the values are going to be used together as e.g. a key for a Dictionary, a Dictionary(Of Integer, Whatever) will be much faster than a Dictionary(Of SomeStructure, Whatever).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文