I am trying to understand explicit struct layout and struct overlaying and i am not seeing behaviour i expect. Given the code below:
class Program
{
static void Main(string[] args)
{
byte[] bytes = new byte[17];
bytes[0] = 0x01; // Age is 1 //IntField1
bytes[1] = 0x00; //IntField1
bytes[2] = 0x00; //IntField1
bytes[3] = 0x00; //IntField1
bytes[4] = 0x02; //IntField2
bytes[5] = 0x00; //IntField2
bytes[6] = 0x00; //IntField2
bytes[7] = 0x00; //IntField2
bytes[8] = 0x41; //CharArray A
bytes[9] = 0x42; //CharArray B
bytes[10] = 0x43; //CharArray C
bytes[11] = 0x44; //CharArray D
bytes[12] = 0x45; //CharArray E
bytes[13] = 0x46; //CharArray F
bytes[14] = 0x00; // \0 decimal 0
bytes[15] = 0x00; // \0 decimal 0
bytes[16] = 0x01; // 1 decimal 1
Console.WriteLine(Marshal.SizeOf(typeof(TestStruct)));
TestStruct testStruct2 = (TestStruct) RawDeserialize(bytes, 0, typeof (TestStruct));
Console.WriteLine(testStruct2);
Console.ReadLine();
}
public static object RawDeserialize( byte[] rawData, int position, Type anyType )
{
int rawsize = Marshal.SizeOf( anyType );
if( rawsize > rawData.Length )
return null;
IntPtr buffer = Marshal.AllocHGlobal( rawsize );
Marshal.Copy( rawData, position, buffer, rawsize );
object retobj = Marshal.PtrToStructure( buffer, anyType );
Marshal.FreeHGlobal( buffer );
return retobj;
}
}
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct TestStruct
{
[FieldOffset(0)]
public int IntField1;
[FieldOffset(4)]
public int IntField2;
[FieldOffset(8)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public char[] CharArray;
[FieldOffset(16)]
public byte SomeByte;
[FieldOffset(8)]
public TestStruct2 SubStruct;
public override string ToString()
{
return string.Format("IntField1: {0}\nIntField2: {1}\nCharArray: {2}\nSomeByte: {3}\nSubStruct:\n{{{4}}}",
IntField1, IntField2, new string(CharArray), SomeByte, SubStruct);
}
}
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct TestStruct2
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public char[] CharArray1;
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] CharArray2;
[FieldOffset(4)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public char[] CharArray3;
public override string ToString()
{
return string.Format("CharArray1: {0}\nCharArray2: {1}\nCharArray3: {2}",
new string(CharArray1), new string(CharArray2), new string(CharArray3));
}
}
I would expect the result from this to be something like:
IntField1: 1
IntField2: 2
CharArray: ABCDEF
SomeByte: 1
SubStruct:
{CharArray1: ABCDEF
CharArray2: ABCD
CharArray3: E }
but the result is:
IntField1: 1
IntField2: 2
CharArray: ABCD
SomeByte: 1
SubStruct:
{CharArray1: ABCD
CharArray2: ABCD
CharArray3: EF}
Why does the CharArray in the TestStruct have a length of 4? I epxected it to have 6 characters ABCDEF but it only contains ABCD. Same for the TestStruct2.CharArray1.
char[] is a reference type, its size is one IntPtr, which can be 4 or 8 Bytes - depending on platform (x86 or x64) and its value in not stored inplace within the structure.
The MarshalAs attribute does not change how the information is stored within the struct, only how it is translated (e.g. to/from unmanaged code).
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