.netstructperformancealignmentdata-formats

If I have three separate values that could all fit into 32 bits, does it make sense to use a uint to store them?


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?


Solution

  • 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.