In C/C ++, once the members of the struct type are declared, the Layout order of the members in the instance is determined, that is, it is in the same order as the member declaration, and by default, Align is always aligned based on the members with the largest space occupied in the structure ); of course, we can also set the memory alignment mode by setting or encoding. We will discuss the (SET) memory alignment in C/C ++, for more information, see my previous interview note, "summarize the questions about setting memory alignment when I did not answer the interview."
However. net hosting environment, CLR provides a more free way to control Layout in struct: We can use the StructLayoutAttribute feature on struct to control the memory Layout of Members when defining struct. By default, the Layout order of fields in the struct instance is the same as that in the Declaration, that is, the [StructLayoutAttribute (LayoutKind. sequential)] feature. The reason for this is that the structure is often used for interaction with unmanaged code. If we are creating a struct type that does not have any interoperability with the unmanaged code, we may want to change this default rule of the C # compiler. Therefore, LayoutKind, except for Sequential members, there are two other Members, Auto and Explicit, which are used to input LayoutKind to StructLayoutAttribute. auto allows the CLR to arrange the fields in the instance according to the optimal method selected by itself. explicit allows the field to set the field sorting method more flexibly according to the FieldOffset we set on the field, but this method is also quite dangerous. If you set the error, the consequences will be more serious. Let's take a few examples to calculate the number of bytes each of the four struct sets?
1. [StructLayout (LayoutKind. Sequential)]
Struct StructDeft // C # The Compiler automatically uses [StructLayout (LayoutKind. Sequential)]
...{
Bool I; // 1 Byte
Double c; // 8 bytes
Bool B; // 1 byte
}
The result of sizeof (StructDeft) is 24 bytes! Aha, only 10 bytes of data occupies 24 bytes of memory, because the default value is LayoutKind. in Sequential), the CLR's Layout Processing Method for struct is the same as the default Processing Method in C/C ++, align ). 10 bytes of data occupies 24 bytes, which seriously wastes the memory. Therefore, if we are creating a struct type that does not have any interoperability with the unmanaged code, it is best not to use the default StructLayoutAttribute (LayoutKind. sequential) feature.
2. [StructLayout (LayoutKind. Explicit)]
[StructLayout (LayoutKind. Explicit)]
Struct BadStruct
...{
[FieldOffset (0)]
Public bool I; // 1 Byte
[FieldOffset (0)]
Public double c; // 8 bytes
[FieldOffset (0)]
Public bool B; // 1 byte
}
The result of sizeof (BadStruct) is 9 bytes. Obviously, Base 9 shows that CLR has not Align any memory Align on the struct ); only 9 bytes of data are occupied for 10 bytes. Obviously, some data is lost, which is why I named struct BadStruct. If [StructLayout (LayoutKind. Explicit)] is used on struct, be careful when calculating FieldOffset. For example, we use the above BadStruct to perform the following test:
StructExpt e = new StructExpt ();
E. c = 0;
E. I = true;
Console. WriteLine (e. c );
The output is no longer 0, but 4.94065645841247E-324, because e. c and e. I share the same byte and execute "e. I = true; "also changed e. c. The CPU is parsing according to the floating point format e. c. (For more information about floating point numbers, see accurately determining whether a floating point number is equal to 0.) So when using LayoutKind. Explicit, do not forget FieldOffset :)
3. [StructLayout (LayoutKind. Auto)]
The result of sizeof (StructAuto) is 12 bytes. Next we will test how the three fields of StructAuto are placed:
Unsafe
...{
StructAuto s = new StructAuto ();
Console. WriteLine (string. Format ("I: {0}", (int) & (s. I )));
Console. WriteLine (string. Format ("c: {0}", (int) & (s. c )));
Console. WriteLine (string. Format ("B: {0}", (int) & (s. B )));
}
// Test Result:
I: 1242180
C: 1242172
B: 1242181
That is, the CLR will adjust the field sequence in the struct. After I is adjusted to c, the StructAuto instance s occupies as little memory as possible and Align the 4 byte memory ), shows the field sequence adjustment result:
4. Empty struct instance Size
Struct EmptyStruct ...{}
The sizeof (EmptyStct) obtained by using Explicit, Auto, and Sequential of LayoutKind above is 1 byte.
Conclusion:
Default (LayoutKind. SequentialIn this case, the CLR treats struct Layout in the same way as the default Processing Method in C/C ++, that is, Align is performed based on the members with the largest space occupied in the structure );
UseLayoutKind. ExplicitIn this case, CLR does not Align the struct with any memory (Align), and we must be careful that it is FieldOffset;
UseLayoutKind. AutoIn this case, the CLR will adjust the field order in the struct so that the instance occupies as little memory as possible and Align 4 bytes memory ).