Zookeeper
1. What is alignment and why:
1. in modern computers, memory space is divided by byte. Theoretically, it seems that access to any type of variables can start from any address, however, the actual situation is that access to specific variables is often performed at specific memory addresses, which requires various types of data to be arranged in space according to certain rules, instead of sequential emissions, this is alignment.
2. Alignment function and cause: Each hardware platform has a big difference in processing the storage space. Some platforms can only access certain types of data from some specific addresses. This may not be the case for other platforms, but the most common problem is that alignment of data storage according to the requirements suitable for their platforms will result in a loss of access efficiency. For example, some platforms start from the even address each time they read data. If an int type (assuming 32-bit) is stored at the beginning of the even address, a read cycle can be read, if the data is stored at the beginning of the odd address, it may take two read cycles and splice the high and low bytes of the two read results to obtain the int data. Obviously, reading efficiency is greatly reduced. This is also a game of space and time.
Ii. Alignment implementation
Usually, we do not need to consider alignment when writing a program. The compiler selects an alignment policy suitable for the target platform for us. Of course, we can also notify the compiler to pass the pre-compilation command to change the Alignment Method for the specified data.
However, because we generally do not need to care about this issue, the editor is aligned with the data storage. If we do not know it, we are often confused about some problems. The most common result is the sizeof result of the struct data structure, which is unexpected. Therefore, we need to understand Alignment Algorithms.
In the same alignment Mode, Struct internal dataThe defined order is different.The struct occupies the memory space as a whole.Different, As follows:
The struct is defined as follows:
Struct
{
Int A;
Char B;
Short c;
};
Struct A contains A four-byte int, A one-byte char, and A two-byte short data. Therefore, the space used by A is 7 bytes. However, the compiler must align the data members in space. Therefore, the sizeof (strcut A) value is8.
Now adjust the sequence of the member variables for this struct.
Struct B
{
Char B;
Int A;
Short c;
};
At this time, it is also a total of 7 bytes of variables, but the value of sizeof (struct B) is12.
The following uses the pre-compiled command # progma pack (value) to tell the compiler to replace the default value with the specified alignment value.
# Progma pack (2)
Struct C
{
Char B;
Int A;
Short c;
};
# Progma pack ()
Sizeof (struct C) value is8.
Modify the alignment value to 1:
# Progma pack (1)
Struct D
{
Char B;
Int A;
Short c;
};
# Progma pack ()
Sizeof (struct D) value is7.
For char data, its own alignment value is 1, for short data is 2, for int, float, double type, its own alignment value is 4, in bytes.
There are four conceptual values:
1. Alignment of the Data Type itself: Alignment of the basic data type described above.
2. Specify the alignment value: # The alignment value specified for progma pack (value.
3. The alignment value of a struct or class: The value with the largest alignment value among its data members.
4. Valid alignment values of data members, struct, and classes: the alignment value of the data itself and the value smaller than the specified alignment value.
With these values, we can easily discuss the data structure members and their alignment. The valid alignment value N is the final value used to determine the data storage address. Valid alignment means "alignment on N", that is, the "Starting address for storing the data % N = 0 ". data variables in the data structure are discharged in the defined order. The starting address of the first data variable is the starting address of the data structure. The member variables of the struct must be aligned and discharged, and the struct itself must be rounded according to its own valid alignment values (that is, the total length occupied by the member variables of the struct must be an integer multiple of the valid alignment values of the struct, ). In this way, you cannot understand the values of the above examples.
Example Analysis:
Analysis example B;
Struct B
{
Char B;
Int A;
Short c;
};
Assume that B is from the address spaceZero x 0000Start emissions. In this example, the specified alignment value is not defined. In the author's environment, this valueThe default value is 4..
The alignment value of the first member variable B is1, Specify an alignment Value4Small, so its valid alignment value is1, So its storage addressZero x 0000Yes0 x 0000% 1 = 0.
The second member variable a has its own alignment value:4, So the valid alignment value is4So it can only be stored at the starting addressZero x 0004ToZero x 0007In the four consecutive bytes0 x 0004% 4 = 0And is close to the first variable.
The third variable c has its own alignment Value2, So the valid alignment value is also2, Which can be stored inZero x 0008ToZero x 0009In the two bytes0 x 0008% 2 = 0. Therefore, B content is stored from 0x0000 to 0x0009.
View the data structure againB's own alignment ValueFor the maximum alignment value (Here is BSo it is 4, so the valid alignment value of the struct is also 4. 0x0009 to 0x0000 = 10 bytes, (10 + 2) % 4 = 0. So0x0000ATo0x000BIt is also occupied by struct B. Therefore, B has 12 bytes from 0x0000 to 0x000B,Sizeof (struct B) = 12;
-----------------------
Alignment (offset of the starting address of the variable to the starting address of the structure)
Char
The offset must be a multiple of sizeof (char), that is, 1.
Int
The offset must be a multiple of sizeof (int), that is, 4.
Float
The offset must be a multiple of sizeof (float), that is, 4.
Double
The offset must be a multiple of sizeof (double), that is, 8.
Short
The offset must be a multiple of sizeof (short), that is, 2.
When each member variable is stored, the space is requested in sequence based on the order in which the structure appears, and the positions are adjusted according to the alignment above. The vacant byte VC is automatically filled.At the same time, to ensure that the size of the structure is a multiple of the number of byte boundary values of the structure (that is, the number of bytes occupied by the Type occupying the maximum space in the structure, therefore, after applying for space for the last member variable, the vacant bytes will be automatically filled as needed.
The following uses the previous example to illustrate how VC stores the structure.
struct MyStruct{double dda1;char dda;int type};
When allocating space for the above structure, VC allocates space for the first member dda1 according to the sequence and alignment of the member variables, the starting address is the same as the starting address of the structure (the offset 0 is just a multiple of sizeof (double). The member variable occupies eight bytes; next, allocate space for the second member dda. the offset of the next address that can be allocated to the starting address of the structure is 8, which is a multiple of sizeof (char, therefore, the dda is stored in an alignment where the offset is 8. This member variable occupies sizeof (char) = 1 byte, and then allocates space for the third member type, in this case, the offset of the next allocable address to the starting address of the structure is 9, not a multiple of sizeof (int) = 4. To meet the offset constraints of alignment, VC automatically fills in three bytes (these three bytes do not have anything). At this time, the next address that can be allocated has a 12 offset to the starting address of the structure, which is exactly sizeof (int) = a multiple of 4, so the type is stored in the biased When the shift is 12, the member variable occupies sizeof (int) = 4 bytes. At this time, the member variables in the entire structure have been allocated space, and the total occupied space is: 8 + 1 + 3 + 4 = 16, which is exactly the number of bytes in the structure (that is, the number of bytes occupied by the Type occupying the maximum space in the structure sizeof (double) = 8) so there is no vacant byte to fill. Therefore, the size of the entire structure is sizeof (MyStruct) = 8 + 1 + 3 + 4 = 16. Among them, three bytes are automatically filled by VC and nothing makes sense.
Next, let's take another example to change the position of the member variable of MyStruct above to the following:
struct MyStruct{char dda;double dda1; int type};
How much space does this structure occupy? In the VC6.0 environment, we can obtain that sizeof (MyStruc) is 24. Based on the space allocation principles mentioned above, we will analyze how VC allocates space for the above structure. (Simple description)
Struct MyStruct {char dda; // The offset is 0. The alignment is satisfied. dda occupies 1 byte. double dda1; // the offset of the next available address is 1, it is not a multiple of sizeof (double) = 8 //. You need to fill in 7 bytes to make the offset change to 8 (which meets the alignment // method). Therefore, VC automatically fills in 7 bytes, dda1 is stored in an address with an offset of 8 //, which occupies 8 bytes. Int type; // the offset of the next available address is 16, which is a factor of sizeof (int) = 4. // The offset satisfies the int alignment mode. Therefore, VC does not need to be automatically filled, type is stored // on the address at the offset of 16, which occupies 4 bytes .}; // Space is allocated to all member variables. The total size of the space is 1 + 7 + 8 + 4 = 20, it is not a multiple of the number of knots in the structure (that is, the number of bytes occupied by the Type occupying the maximum space in the structure) sizeof // (double) = 8, therefore, four bytes need to be filled to meet the structure size as a multiple of // sizeof (double) = 8.
Therefore, the total size of this structure is: sizeof (MyStruc) is 1 + 7 + 8 + 4 + 4 = 24.Among them, 7 + 4 = 11 bytes are automatically filled by VC, and nothing makes sense.
The special processing of the structure storage by VC does increase the speed of the CPU storage variable, but sometimes it also brings some trouble. We also shield the default alignment of the variables, you can set the alignment of variables.
# Pragma pack (n) is provided in VC to set the variable to n-byte alignment. N-byte alignment means the offset of the Start address of the variable. First, if n is greater than or equal to the number of bytes occupied by the variable, the offset must meet the default alignment mode, second, if n is less than the number of bytes occupied by the variable type, the offset is a multiple of n, and the default alignment is not required. The total size of the structure also has a constraint, which is divided into 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 space occupied by the largest variable;
Otherwise, it must be a multiple of n. The following is an example of its usage.
# Pragma pack (push) // save alignment # pragma pack (4) // set to 4-byte alignment struct test {char m1; double m4; int m3 ;}; # pragma pack (pop) // restore alignment
The size of the above structure is 16. Next we will analyze its storage situation. First, we will allocate space for m1, and its offset is 0, which meets our own alignment (4-byte alignment ), m1 occupies 1 byte. Then we start to allocate space for m4. At this time, the offset is 1 and three bytes need to be supplemented. In this way, the offset must be a multiple of n = 4 (because sizeof (double) is greater than n ), m4 occupies 8 bytes. Then allocate space for m3. At this time, the offset is 12, which must be a multiple of 4. m3 occupies 4 bytes. At this time, space has been allocated for all member variables. A total of 16 bytes are allocated, which is a multiple of n. If you change # pragma pack (4) to # pragma pack (16), the size of the structure is 24. (Please analyze it by yourself)
========================================== ========================
Companies such as Intel and Microsoft once had a similar interview question:
#include
#pragma pack(8)struct example1{short a;long b;};struct example2{char c;example1 struct1;short e;};#pragma pack()int main(int argc, char* argv[]){example2 struct2;cout << sizeof(example1) << endl;cout << sizeof(example2) << endl;cout << (unsigned int)(&struct2.struct1) - (unsigned int)(&struct2) << endl;return 0;}
What is the input result of the program?
The answer is:
8
16
4
Answers to interview questions
So far, we can answer Intel and Microsoft interview questions comprehensively.
Line 1 in the Program # pragma pack (8) although the ing is specified as 8, the maximum number of members in struct example1 is
The size is 4 (long variable size is 4), so struct example1 is still bounded by 4 bytes, and the size of struct example1
Is 8, that is, the output result of 18th rows;
Struct example2 contains struct example1. the maximum size of simple data members contained in struct example1 is 2 (short
Variable e), but because it contains struct example1, the maximum member size in struct example1 is 4, struct
Example2 should also be bounded by 4, # The peer bound in pragma pack (8) does not work for struct example2, so 19 rows
The output result is 16;
Since the members in struct example2 are 4-aligned, the char variable c should be followed by three null values, followed
The memory space of the struct1 member. The output result of 20 rows is 4.
union A{int a[5];char b;double c;};struct B{int n;A a;char c[10];}
Sizeof (B) =?
Answer:
union A: { int a[5]; //20 char b; //1 double c; //8 }
What I think is that variables in union share the memory. The longest value shall prevail, that is, 20. Otherwise, sizeof (A) = 24,
The default memory alignment of each variable in A must be aligned with the maximum double 8 bytes, so it should be sizeof (A) = 24.
Struct B {int n; // 4 bytes A; // 24 bytes char c [10]; // 10 bytes };
It actually occupies 38 bytes, but since A is 8 bytes aligned, int n and char c [10] also need 8 bytes aligned, A total of 8 + 24 + 16 = 48
Zookeeper