2

I wrote a small Console application to test the sizeof operator:

public class Program
{
    public static unsafe void Main(string[] args)
    {
        // Native
        Console.WriteLine("The size of bool is {0}.", sizeof(bool));
        Console.WriteLine("The size of short is {0}.", sizeof(short));
        Console.WriteLine("The size of int is {0}.", sizeof(int));
        Console.WriteLine("The size of long is {0}.", sizeof(long));

        // Custom
        Console.WriteLine("The size of Bool1 is {0}.", sizeof(Bool1));
        Console.WriteLine("The size of Bool2 is {0}.", sizeof(Bool2));
        Console.WriteLine("The size of Bool1Int1Bool1 is {0}.", sizeof(Bool1Int1Bool1));
        Console.WriteLine("The size of Bool2Int1 is {0}.", sizeof(Bool2Int1));
        Console.WriteLine("The size of Bool1Long1 is {0}.", sizeof(Bool1Long1));
        Console.WriteLine("The size of Bool1DateTime1 is {0}.", sizeof(Bool1DateTime1));

        Console.Read();
    }
}

public struct Bool1
{
    private bool b1;
}

public struct Bool2
{
    private bool b1;
    private bool b2;
}

public struct Bool1Int1Bool1
{
    private bool b1;
    private int i1;
    private bool b2;
}

public struct Bool2Int1
{
    private bool b1;
    private bool b2;
    private int i1;
}

public struct Bool1Long1
{
    private bool b1;
    private long l1;
}

public struct Bool1DateTime1
{
    private bool b1;
    private DateTime dt1;
}

that gives the following output:

sizeof result

It seems that the order in which the fields are declared plays a role in the size of the structure.

I was expecting that Bool1Int1Bool1 returns a size of 6 (1 + 4 + 1) but it gives 12 instead (I suppose 4 + 4 + 4??) ! So it seems that the compiler is aligning the members by packing everyting by 4 bytes.

Does it change something if I'm on a 32 bits or 64 bits system?

And second question, for the test with the long type, the bool is packed by 8 bytes this time. Who can explain this?

Bidou
  • 7,378
  • 9
  • 47
  • 70
  • 5
    You might want to take a look [here](http://www.developerfusion.com/article/84519/mastering-structs-in-c/) – Patryk Ćwiek Jun 04 '13 at 21:06
  • possible duplicate of [struct sizeof result not expected](http://stackoverflow.com/questions/1913842/struct-sizeof-result-not-expected) – Michael Burr Jun 05 '13 at 06:26

2 Answers2

2

That's because the compiler aligns member variables of the structs to allow CPU read and write their values quickly.

Here, as you observed, it adds 3 dummy bytes after each bool.

Marcin Jedynak
  • 3,697
  • 2
  • 20
  • 19
  • 1
    why didn't it align them for Bool2Int1? – Dmitry Khryukin Jun 04 '13 at 21:49
  • @DmitryKhryukin. Basically it aligns variables based on their size. `bool`'s are one byte so they are aligned on a one byte boundary, `int`'s are four bytes, so they are aligned on four byte boundaries. So for `Bool2Int`, 'b1' is at offset 0, `b2` is at offset 1, and `i1` is at offset 4. – shf301 Jun 05 '13 at 03:01
  • what is the difference with Bool1Int1Bool1? I don't see it in your answer. – Dmitry Khryukin Jun 05 '13 at 03:38
  • @DmitryKhryukin. The compiler observes that the biggest member variable type is int - 4 bytes, so it tries to put everything in chunks of 4 bytes. In Bool2Int1 it can pack 2 first bools in 4 bytes, in Bool1Int1Bool1 they are separated by int, so it has to align them both. – Marcin Jedynak Jun 05 '13 at 14:22
2

That's because the compiler aligns members so their access speed is optimized, not their memory footprint.

You can add

[StructLayout(LayoutKind.Sequential, Pack=1)]

before the structure definition and it should align in 1 byte spaces.

Aether McLoud
  • 732
  • 1
  • 7
  • 20