Physical Layout of Data - StructLayout
This week I was taking a close look into various InterOp related stuff for a code review purpose.While doing so the way CLR controls the physical layout of a data structure in memory caught my attention.This is what I intend to discuss here.
When we are declaring a set of fields for a structure or class the ordering of variables in the code has no impact on the physical ordering of the variables in memory(unmanaged memory) unless we are instructing the CLR specifically to do so.This can be done by applying the System.Runtime.InteropServices.StructLayoutAttribute attribute on the class or structure.This attribute accepts a value from enumeration System.Runtime.InteropServices.LayoutKind as constructor.This enumeration has 3 values:
- Auto - Runtime automatically decides about the layout of the data structure.
- Sequential - The fields are layout sequentially in the memory.This is determined by pack size specified by System.Runtime.InteropServices.StructLayoutAttribute.PackSize property.This layout can be non contiguous as well.
- Explicit - The position of each member is explicitly controlled by specifying the System.Runtime.InteropServices.FieldOffsetAttribute class.This attribute is applied at field level and accepts the offset in bytes as constructor as shown below:
[StructLayout(LayoutKind.Explicit)]
public class TestObject
{
[FieldOffset(0)]
public Int32 i;
[FieldOffset(8)]
public Int32 j;
[FieldOffset(4)]
public Int32 k;
}
Now to test whether offset is truly taking effect I wrote few lines of unsafe code as shown below:
static void Main(string[] args)
{
TestObject t = new TestObject();
t.i = 10;
t.j = 20;
t.k = 30;
unsafe
{
fixed (int* p = &t.i)
{
//i has first position
Console.WriteLine("Value Of i is " + *p);
//j has third position
Console.WriteLine("Value Of j is " + *(p+2));
//k has second position
Console.WriteLine("Value Of k is " + *(p+1));
}
}
}
And the program prints the values correctly meaning this works well.WoW!!!