This is my reprint of the article ~ The original source I did not find.
The whole concept of the article is explained very clearly, but there are some mistakes in the area ... (red flag)
I'll give you a supplement to the other blog posts: http://soft.chinabyte.com/database/9/12297509.shtml
The above connected experiments can be supplemented.
One, what is alignment, and why to align:1The memory space in modern computers is divided by Byte, and in theory it seems that access to any type of variable can start at any address, but it is often accessed at specific memory addresses when accessing a particular variable, which requires all types of data to be spatially arranged according to certain rules, Instead of sequentially one by one emissions, that's the alignment. 2the role and cause of alignment: the processing of storage space varies greatly with each hardware platform. Some platforms can only access certain types of data from certain specific addresses. Other platforms may not, but the most common is the loss of access efficiency if data storage is not aligned as required for its platform. For example, some platforms each read from the even address, if an int (assuming 32-bit) if it is stored at the beginning of the even address, then a reading period can be read out, and if stored in the location of the odd address, it may require 2 read cycles, and two read the results of the high and low Byte is pieced together to get the int data. Obviously, the reading efficiency is much lower. This is also the game of space and time. Second, the implementation of the alignment usually, when we write the program, we do not need to consider the alignment problem. The compiler chooses the alignment strategy for the target platform for us. Of course, we can also notify the compiler to pass the precompiled instructions and change the alignment of the specified data. However, because we generally do not need to care about this problem, because the editor to the data storage alignment, and we do not understand, often will be confused about some problems. The most common is the sizeof result of the struct data structure, unexpectedly. To do this, we need to understand the alignment algorithm. Alignment algorithm: Because of the different platforms and compilers, now I use the GCC version3.2The . 2 Compiler (32-bit x86 platform) is an example of how the compiler aligns the members of a struct's data structure. The structure is defined as follows:structA {intA; Charb; Shortc;}; Struct A contains a 4-byte-length int, a 1-byte length char, and a 2-byte length of short data. So the space used for a should be 7 bytes. But because the compiler wants to align the data members spatially. So using the sizeof (Strcut A) value is 8. Now adjust the order of the member variables to the struct body. structB {Charb; intA; Shortc;}; This is also a total of 7 byte variables, but sizeof (structB) has a value of 12. Below we use precompiled Directives#pragmaPack (value) to tell the compiler to replace the default with the alignment value we specify.#progma Pack (2)/*specify to align by 2 bytes*/structC {Charb; intA; Shortc;}; #progma Pack ()/*Cancel the specified alignment, restore the default alignment*/sizeof(structC) The value is 8. Modify the alignment value to 1: #progma Pack (1)/*specify to align by 1 bytes*/structD {Charb; intA; Shortc;}; #progma Pack ()/*Cancel the specified alignment, restore the default alignment*/sizeof(structD) value is 7. For char type data, its own alignment value is 1, for the short type is 2, for int,floatA double that has its own alignment value of 4(double should be 8 bytes), in bytes. There are four concept values in this:1The alignment value of the data type itself: is the self-aligning value of the underlying data type that was confessed above. 2) to specify the alignment value:#pragmaWhen the pack (value) is specified, the value is aligned.3a struct or class that has its own alignment value: The value that is the largest of its members in its own alignment. 4valid alignment values for data members, structs, and classes: their own alignment values and the smaller values in the specified alignment values. With these values, we can easily discuss the members of a specific data structure and its own alignment. The valid alignment value n is the value that is ultimately used to determine how the data is stored, most importantly. Effectively aligns N, which means "align on n", meaning that the data"Store start Address%n=0"The data variables in the structure are emitted in the order in which they are defined. The starting address of the first data variable is the starting address of the structure. The member variables of the struct should be aligned with the emission, and the structure itself should be rounded according to its own valid alignment value (that is, the total length of the struct member variable is required to be an integral multiple of the effective alignment value of the struct, as the following example understands). This makes it easy to understand the values of several examples above. Example Analysis: analysis example B;structB {Charb; intA; Shortc;}; Suppose B starts discharging from the address space 0x0000. In this example, the specified alignment value is not defined, and in the author's environment, the value defaults to 4. The first member variable B has a self-aligning value of 1, which is smaller than the specified or default alignment value of 4, so its valid alignment value is 1, so its storage address 0x0000 conforms to 0x0000%1=0The second member variable A has its own alignment value of 4, so the valid alignment value is also4, so it can only be stored in four contiguous byte spaces with a starting address of 0x0004 to 0x0007, and a review 0x0004%4=0, and immediately next to the first variable. The third variable, C, has its own alignment value of 2, so the valid alignment value is also 2, which can be stored in the two byte space of 0x0008 to 0x0009, in accordance with 0x0008%2=0。 So everything from 0x0000 to 0x0009 is stored in B content. Then look at the data structure B's own alignment value for its variable maximum alignment value (here is B) so is 4, so the structure of the effective alignment value is also 4. 0x0009 to 0x0000=10 bytes, depending on the requirements of the structural rounding, (Ten+2)%4=0。 So 0x0000a to 0x000b is also occupied by struct B. So b a total of 12 bytes from 0x0000 to 0x000b,sizeof(structB) = Ain the same vein, analyze the above example C:#pragmaPack (2)/* Specify 2-byte alignment */structC {Charb; intA; Shortc;};#pragmaPack ()/* Cancels the specified alignment, restores the default alignment */The first variable B has its own alignment value of 1, the specified alignment value is 2, so its valid alignment value is 1, assuming that C starts from 0x0000, then B is stored in 0x0000, in accordance with 0x0000%1=0The second variable, with its own alignment value of 4, specifies that the alignment value is 2, so the valid alignment value is 2, so the order is stored in the 0x0002,0x0003、0x0004, 0x0005 four consecutive bytes, in accordance with 0x0002%2=0. The third variable C has its own alignment value of 2, so the valid alignment value is 2, stored in 0x0006, 0x0007, in accordance with 0x0006%2=0。 So from 0x0000 to 0x00007 a total of eight bytes is stored in the C variable. and C has its own alignment value of 4, so the valid alignment value for C is 2. Another 8%2=0, c occupies only eight bytes from 0x0000 to 0x0007. So sizeof (structC) =8with the above explanations, I believe you should have a clear understanding of the concept of byte alignment in C. In the network program, mastering this concept is very important, oh, between the different platforms (such as between Windows and Linux) to pass 2 of streams (such as the structure), then in these two platforms must define the same alignment, or some inexplicable error, but it is difficult to troubleshoot the OH^_^.
Add:
structMyStruct {Doubledda1; CharDDA; inttype}; When allocating space for the above structure, the VC allocates space for the first member DDA1 based on the order and alignment of the member variables, and the starting address is the same as the starting address of the structure (just 0 of the offset is just the size of sizeof (Double), the member variable occupies the sizeof (Double) = 8 bytes; Then allocate space for the second member DDA, at which point the next assignable address has an offset of 8 for the starting address of the struct, which is sizeof (Char), so the DDA is stored at an offset of 8 where the alignment is satisfied, and the member variable occupiessizeof(Char) = 1 bytes; Next, allocate space for the third member type, at which point the next assignable address will have an offset of 9 for the start address of the struct, not sizeof (intA multiple of the =4, in order to satisfy the alignment of the offset constraint problem, VC automatically fill 3 bytes (This three bytes did not put anything), then the next assignable address for the structure of the starting address of the offset of 12, just the sizeof (int) =4, so the type is stored at an offset of 12, which takes up sizeof (int) = 4 bytes; The member variable of the entire structure is already allocated space, the total space occupied is:8+1+3+4= -, which is exactly the number of byte boundaries of the struct (that is, the number of bytes in the structure that occupies the maximum space. sizeof (Double)=8), so no empty bytes need to be populated. So the size of the entire structure is:sizeof(mystruct) =8+1+3+4= -, where 3 bytes are VC auto-populated, without any meaningful things. In the following example, swap the position of the member variable of the above mystruct to make it the following situation:structMyStruct {CharDDA; Doubledda1; inttype}; How much space does this structure occupy? In the VC6.0 environment, sizeof (MYSTRUC) can be obtained as 24. According to some principles of allocating space mentioned above, this paper analyzes how VC allocates space for the above structure. (Simple description)structMyStruct {CharDda//The offset is 0, the alignment is satisfied, and the DDA occupies 1 bytes; DoubleDDA1;//the offset of the next available address is 1, not sizeof (double) =8//multiples of 7 bytes to make the offset to 8 (to satisfy the alignment//), so VC automatically fills 7 bytes, dda1 is stored at an offset of 8//address, it occupies 8 bytes. intType//The offset of the next available address is 16, which is the =4 of sizeof (int)//number, which satisfies the alignment of int, so no VC auto-fill is required, type is stored//placed at an offset of 16, it occupies 4 bytes. };//all member variables are allocated space, the total size of the space is 1+7+8+4=20, not the structure//the number of section boundaries (that is, the number of bytes in the structure that occupy the largest space in the struct. sizeof//(double) =8), so a multiple of 4 bytes is required to satisfy the size of the structure to//the multiple of the sizeof (double) =8. so the total size of the structure is:sizeof(Mystruc) is 1 +7+8+4+4= -。 The total of which is 7 +4=The 11 bytes are automatically populated by VC and do not put anything meaningful. VC storage of the structure of the special processing does increase the speed of the CPU storage variables, but sometimes it brings some trouble, we also block out the default alignment of variables, we can set the alignment of variables. The VC provides#pragmaPack (n) to set the variable to n-byte alignment. N-byte alignment means that the offset of the starting address of the variable is in two cases: first, if n is greater than or equal to the number of bytes occupied by the variable, then the offset must satisfy the default alignment, and second, if N is less than the number of bytes occupied by the type of the variable, then the offset is a multiple of n, not the default The total size of the structure also has a constraint, in the following two cases: if n is greater than the number of bytes occupied by all member variable types, the total size of the structure must be a multiple of the amount of space occupied by the variable occupying the largest space; (PS: #pragma pack (n) must be smaller than a certain alignment to compress space, or it is the same as the default alignment, referring to the above blog post, this macro command is used to change the data type itself alignment of the item) otherwise must be a multiple of n. The following examples illustrate their usage. #pragmaPack (push)//Save Alignment State #pragmaPack (4)//set to 4-byte alignment structTest {CharM1; DoubleM4; intm3; }; #pragmaPack (POP)//Restoring the Alignment statethe size of the above structure is 16, the following analysis of its storage, the first to allocate space for M1, its offset is 0, to meet our own set of alignment (4-byte alignment), M1 occupies 1 bytes. It then begins allocating space for the M4, where the offset is 1 and 3 bytes are required, so the offset is satisfied with nMultiples of =4 (because sizeof (Double) is greater than N, M4 occupies 8 bytes. The M3 is then allocated space, at which point the offset is 12, satisfies the multiple of 4, and M3 occupies 4 bytes. At this point, all member variables have been allocated space, with a total of 16 bytes allocated, which satisfies a multiple of n. If you put the above#pragmaPack (4) is changed to #pragma pack (16), then we can get the size of the structure to 24. (Ask the reader to analyze it yourself)third, look at the following example#pragmaPack (8)structs1{CharA; Longb; }; structS2 {CharC; structS1 D; Long Longe; }; #pragmaPack ()sizeof(S2) result is 24. Member alignment has an important condition in which each member is aligned individually. That is, each member is aligned in its own way. This means that although the above specifies a 8-byte alignment, not all members are aligned in 8-byte terms. The rule of alignment is that each member is aligned to the lesser of its type's alignment parameters (usually the size of this type) and the specified alignment parameters (here is 8 bytes). And the length of the structure must be an integer multiple of all the alignment parameters used, not enough to fill the empty bytes. In S1, member A is 1 bytes by default by 1-byte alignment, the alignment parameter is 8, the two values are 1,a by 1 bytes, the member B is 4 bytes, by default is 4 byte aligned, then by 4 byte alignment, so sizeof (S1) should be 8; S2, C and a in S1, as in 1-byte alignment, and D is a struct, it is 8 bytes, what is it aligned? For a struct, its default alignment is the largest of the alignment parameters used by all its members, and S1 is 4. Therefore, member D is aligned by 4 bytes. The member E is 8 bytes, it is the default by 8-byte alignment, as specified, so it is on the 8-byte boundary, at this point, 12 bytes have been used, so added 4 bytes of space, starting from the 16th byte to place the member E. At this point, the length is 24, can be 8 (member E by 8 byte alignment) Divisible. In this way, 24 bytes are used altogether. The memory layout of a B S1: One**,1111, c s1.a s1.b d S2 Memory layout:1***, One**,1111,****11111111Here are three important points:1Each member is aligned in its own way and can minimize the length. 2The default alignment of a complex type, such as a struct, is the alignment of its longest member, so that the length can be minimized when the member is a complex type. 3The length of the alignment must be an integer multiple of the largest alignment parameter in the member, so that each item is aligned to the boundary when the array is processed. Supplemental part of the original link: http://soft.chinabyte.com/database/9/12297509.shtml
C Language: Memory byte alignment explained [reprint]