public struct TestStruct
{
public int first;
public int second;
public int third;
}
Marshal.SizeOf returns 12, which is what I assume because the ints are 4 bytes each. If I were to change third to a double instead of an int, I would expect Marshal.SizeOf to return 16. It does. But if I were to add a fourth that was a double, Marshal.SizeOf returns 24, when I expect 20. I could have 10 ints and it would end up each int counted as 4bytes each. But if I add a double in after 3 ints, the size isn't what I expect.
public struct TestStruct //SizeOf 12
{
public int first;
public int second;
public int third;
}
public struct TestStruct //SizeOf 16
{
public int first;
public int second;
public double third;
}
public struct TestStruct //SizeOf 24, but I feel like it should be 20
{
public int first;
public int second;
public double third;
public int fourth;
}
Where has my thinking led me astray?
In addition to JimR's answer, you can explicitly change this behaviour using the StructLayout attribute:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TestStruct // sizeof is now 20
{
public int first;
public int second;
public double third;
public int fourth;
}
You've told the compiler that this struct is sequentially laid out, and that the packing type should be 1, which means that all fields are laid out directly after each other. Pack 0 (the default) tells the compiler to use the current platforms padding.. while anything else (in multiples of 2) will lay it out in those specific boundaries. I would advise against this though.. it could become unpredictable depending on your usage.
For more info, see this MSDN article: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute.pack.aspx
You're not considering any padding that is put in the structure.
In some cases it is more efficient for a CPU to read something at a multiple of it's size. For instance, some CPUs like ints aligned on 4 byte boundaries. Some CPUs have to issue 2 reads if an int is not aligned.
int, float and double are especially sensitive to alignment when they might be touched by SSE type instructions on Intel processors.
I believe the answer lies in the alignment of the data fields.
For example, by default a struct defined with C# is going to have this attribute on it:
[StructLayout(LayoutKind.Sequential)]
If you look at the definition of LayoutKind.Sequential, it states:
LayoutKind Enumeration
The members of the object are laid out sequentially, in the order in which they appear when exported to unmanaged memory. The members are laid out according to the packing specified in StructLayoutAttribute.Pack, and can be noncontiguous.
If you were to specify this attribute instead:
[StructLayout(LayoutKind.Auto)]
You would get the size you expect - 20.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With