C-language structural body alignment
The C-language structure alignment is also a commonplace topic. It is basically a must for the interview question. Although the content is very basic, but carelessly will be mistaken. Write a struct, and then sizeof, will you often be surprised by the results? SizeOf's results tend to be bigger than the total length of the variable you're declaring, what's going on?
When I started to learn, I was plagued by such problems for a long time. In fact, a lot of relevant articles, feel that there is not a lot of clarity. How exactly does the structure align?
Some people give a summary of the principle of alignment, specifically where to see the present has not been remembered, here refers to the experience of predecessors (in the absence of #pragma pack macro case):
Principle 1, data member alignment rules: A data member of a struct (struct or union Union), where the first data member is placed at offset 0, and the starting position of each data member store at a later time begins with an integer multiple of that member size (for example, int is 4 bytes in a 32-bit machine, To start storage from an integer multiple address of 4).
Principle 2, struct as a member: if there are some struct members in a struct, the struct member is stored from the integer multiple address of its internal maximum element size. (struct A contains elements such as char,int,double in a struct b,b, and that B should be stored in multiples of 8.) )
Principle 3, finishing work: The total size of the structure, that is, the result of sizeof, must be the largest member of its internal integer times, insufficient to complete.
How do these three principles relate to each other? Let's look at the following examples to deepen our understanding through examples.
Example 1:struct {
Short A1; Short A2; Short A3; }a;
struct{long A1; Short A2; }b;
sizeof (A) = 6; This is a good understanding, three short is 2.
sizeof (B) = 8; Is it 2 bytes larger than expected? Long is 4,short to 2,
The whole is 8 because of principle 3.
Example 2:struct a{
int A; Char b; Short C; };
struct b{char B; int A; Short C; };
sizeof (A) = 8; int is 4,char to 1,short for 2, which is used in principle 1 and Principle 3.
sizeof (B) = 12; Is it beyond the scope of your expectations? Char is 1,int to 4,short for 2, how can it be 12? It is also principle 1 and principle 3.
Dig into it, why, we can look at the layout of the memory.
Memory layout of a B c A: 1111, 1*, 11
Memory layout of B a C B: 1***, 1111, 11**
Where the asterisk * represents the populated bytes. A, why do you want to add a byte after B? Because C is short, its starting position is a multiple of 2, which is principle 1. There is no supplement to C, since B and C occupy 4 bytes, and the entire a occupies a multiple of 4, that is, a multiple of the maximum member int type, so there is no need to add it.
B, B is a char that adds 3 bytes to the 1,b, since a is an int of 4, and according to Principle 1, the starting position is a multiple of 4, so B is followed by a 3-byte supplement. C is supplemented by two bytes, according to principle 3, the entire B takes up space to be a multiple of 4, after C does not add, the entire B space is 10, does not match, so to add 2 bytes.
Let's look at an example of struct members in a structure:
Example 3:struct a{
int A;
Double b;
float C;
};
struct b{
Char e[2];
int F;
Double g;
Short h;
struct A i;
};
sizeof (A) = 24; This is a good understanding, int is 4,double for 8,float is 4, the total length is a multiple of 8, padded, so the whole A is 24.
sizeof (B) = 48; Look at the memory layout of B.
The memory of E F g h i B: 11* *, 1111, 11111111, 11 * * * * * *, 1111* * * *, 11111111, 1111 * * * *
I'm actually the memory layout of a. The starting position of I is a multiple of 24, so the H should be followed. The memory layout of B is clear, the structure of the alignment of the basic even mastered.
All of these are not #pragma pack macros, if you have #pragma pack macro, the alignment is defined by the macro. For example, with #pragma pack (1) in front of the structure, the layout of the memory will change completely. sizeof (A) = 16; sizeof (B) = 32;
With #pragma pack (1), the memory will no longer follow principle 1 and Principle 3, which is aligned by 1 bytes. Yes, this is not an ideal world without memory alignment.
Memory layout of a B c A: 1111, 11111111, 1111
E F g H i
Memory layout of B: 11, 1111, 11111111, 11, 1111, 11111111, 1111
What about the result of the #pragma pack (2)? #pragma pack (4)? Leave it to yourself to think about it, and believe that there is no problem.
There is also a common case in which the structure contains bit field fields. A bit domain member cannot be taken as a single sizeof value. C99 specifies that int, unsigned int, and bool can be used as bit field types, but almost all compilers extend this to allow the existence of other type types.
The primary purpose of using bit fields is to compress the storage, with the approximate rule of: 1) If the adjacent bit field field is of the same type and its bit width is less than the type sizeof size, then the following field will be stored next to the previous field until it cannot be accommodated;
2) If the adjacent bit field field is the same type, but its bit width is greater than the type sizeof size, then the next field will start from the new storage unit, its offset is an integer multiple of its type size, 3) if the type of the adjacent bit field fields is different, the specific implementation of the compiler differs, VC6 take the non-compression method, dev-c++ adopt compression method;
4) If the bit field fields are interspersed with non-bit field fields, no compression is performed, and 5) The total size of the entire struct is an integer multiple of the size of the widest base type member.
Let's take a look at the example. Example 4:struct a{
Char F1:3; Char F2:4; Char F3:5; };
Memory layout of a B c A: 111, 1111 *, 11111 * * *
The bit field type is char, the 1th byte can only hold the lower F1 and F2, so F2 is compressed into the 1th byte, and F3 only starts with the next byte. Therefore, the result of sizeof (A) is 2.
Example 5:struct b{
Char F1:3; Short F2:4; Char F3:5; };
Due to the different types of neighboring bit fields, the sizeof is 6 in VC6 and 2 in dev-c++.
Example 6:struct c{
Char F1:3; char F2; Char F3:5; };
Non-bit field fields are interspersed in which no compression is generated, and the size obtained in VC6 and Dev-c++ is 3.
Consider a question, why design memory alignment? If the architecture is misaligned, the members will be stored one after the other, and obviously the alignment will be wasted space. So why use alignment? The alignment and misalignment of the architecture is a trade-off between time and space. The alignment saves time. Assuming that the word length of an architecture is W, it also assumes that the most frequent and important process for this architecture is to handle the data with a width of W. It is also designed to take precedence over the efficiency of W-bit data operations. Interested can Google a bit, others can explain to you, a lot of truth.
Finally, by the way, in the design of the structure, the general will take a custom, that is, the type of small space occupied in front, occupy a large number of types in the back, so that you can relatively save some of the alignment space.
C-language structural body alignment