[From] http://www.cnblogs.com/happyhippy/archive/2007/04/12/710927.aspx
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. For more information about memory alignment in C/C ++, refer to an interview note I wrote earlier.Summary: The questions about setting memory alignment were not answered during 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, fields in the struct instance are layout on the stack) the order is the same as the declared order , that is, the [structlayoutattribute (layoutkind. sequential)] feature. The reason for this is structures are often used in scenarios where Code interactions are not hosted. 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 also two members, auto and explicit, which are used to pass layoutkind to structlayoutattribute. auto allows the CLR to arrange the fields in the instance in the optimal way selected by itself , and pass in layoutkind. explicit allows the field to set the field sorting method more flexibly according to the fieldoffset set on the field. However, this method is quite risky, if an error is set, the result will be severe. 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 byte
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 byte
[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 details about floating point numbers, refer toAccurately determine 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 results:
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's layout Processing Method for struct is the same as the default Processing Method in C/C ++, that isAlign);
UseLayoutkind. ExplicitIn this case,CLR does not align the struct with any memory (align)And we should be careful that it is fieldoffset;
UseLayoutkind. AutoIn this case, CLR will adjust the field order in the struct so that the instance occupies as little memory as possible, andAlign ).
Happyhippy
Author: silent void
Source: http://happyhippy.cnblogs.com/
This statement must be retained and stated inArticleThe source text link is provided at the starting position.