Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StructLayoutAttribute.Pack confusion

Tags:

c#

I have some problem interpreting the result of two pieces of code.

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 0)]
struct MyStruct
{
    public byte b1;
    public char c2;
    public int i3;
}

public class Example
{
    public unsafe static void Main()
    {
        MyStruct myStruct = new MyStruct();
        byte* addr = (byte*)&myStruct;    
        Console.WriteLine("Size:      {0}", sizeof(MyStruct));    
        Console.WriteLine("b1 Offset: {0}", &myStruct.b1 - addr);
        Console.WriteLine("c2 Offset: {0}", (byte*)&myStruct.c2 - addr);
        Console.WriteLine("i3 Offset: {0}", (byte*)&myStruct.i3 - addr);    
        Console.ReadLine();
    }
}

The above result is

Size :      8

b1 Offset:  0
c2 Offset:  2
i3 Offset:  4

If I comment out public char c2; and Console.WriteLine("c2 Offset: {0}", (byte*)&myStruct.c2 - addr);, I would get

Size :      8

b1 Offset:  0
i3 Offset:  4

Now I think I can explain the second scenario, where the default packing size is the size of the largest element size of myStruct when Pack = 0. So it is 1 byte + 3 bytes of padding + 4 bytes = 8.

But the same does not seem apply for the first scenario. My expected result would be (1 byte + 3 bytes of padding) + (2 bytes for char + 2 bytes of padding) + (4 bytes for int). So the total size should be 12 as the packing size of 4 byte(the size of int), and the respective offset are 0, 4, 8.

What am I missing here?

Thanks


1 Answers

To understand alignment it might be helpful to think about something reading your struct in X-byte chunks (where X is your type alignment). In your examples that X is 4. If no padding is added, reading first 4 bytes of your first struct (with char) will read byte, char, and then one byte of the next int field. This (avoid reading partial field bytes) is why padding is needed. To "fix" the problem - one byte of padding is needed. Then first 4-byte read will read byte and char fields (and one byte of padding), and next 4-byte read will read integer field. It's wasteful to add padding as you expected, because you can achieve the same goal with smaller total size (8 bytes over your expected 12).

like image 110
Evk Avatar answered Oct 27 '25 03:10

Evk