This problem for a long time, looked up a lot of information, online opinions, collation as follows:
for details on memory completion, please follow the next article: C + + memory completion mechanism
I. Initial explanation of memory alignment
Memory alignment can be summed up in a sentence:
"Data items can only be stored in memory locations where the address is an integer multiple of the size of the data item (an address that is evenly divisible by 4 and an address divisible by 8, respectively)
)”
For example, the int type occupies 4 bytes, and the address can only be located in 0,4,8.
Example 1:
#include <stdio.h>
struct xx{
Char b;
int A;
int C;
Char D;
};
int main ()
{
struct XX BB;
printf ("&a =%p/n", &BB.A);
printf ("&b =%p/n", &bb.b);
printf ("&c =%p/n", &BB.C);
printf ("&d =%p/n", &BB.D);
printf ("sizeof (XX) =%d/n", sizeof (struct xx));
return 0;
}
The results of the implementation are as follows:
&a = Ffbff5ec
&b = Ffbff5e8
&c = ffbff5f0
&d = Ffbff5f4
sizeof (XX) = 16
You will find that there are 3 bytes left between B and a, that is, the 0xffbff5e9,0xffbff5ea,0xffbff5eb after B is empty, and a is stored directly in 0xffbff5ec, because the size of a is 4 and can only be stored in the position of 4 integer multiples. The size of the printing xx will be found, is 16, some people may want to ask, B after the empty 3 bytes, it should also be 13 ah? What about the other 3? This later read this article will understand a bit more deeply, here is simply said to be the 3 bytes behind D, will also be wasted, that is, the 3 bytes are also occupied by the structure.
You can easily modify the structure of the structure to reduce the use of memory, for example, you can define a struct as:
struct xx{
Char b;
Char D;
int A;
int C;
};
So the size of this structure is 12, save a lot of space, you can see, in the definition of the structure, it is important to consider the effect of memory alignment, so that our program occupies a smaller amount of memory.
Two. Default alignment factor for the operating system
By default, in order to facilitate access to and management of data elements in structs and classes, when the length of a data element within a struct or class is less than the machine word size, the Unit is aligned with the longest data element in the struct or class. In other words, the length of a struct or class must be an integer multiple of the longest data element . If there is a data element in the struct or class that is longer than the length of the machine, the Unit is aligned in the machine's word size. Contiguous elements of the same type in a struct or class will be consistent in contiguous space, and in arrays.
For example: (machine word length is 32 bits)
struct{
Short A1;
Short A2;
Short A3;
}a;
Class B
{
Public
int A;
static int b;
B ();
~b ();
};
struct{
float A;
int b;
char c;
}c;
Find sizeof (A), sizeof (B), sizeof (C);
The A,short type variable accounts for 2 bytes, so sizeof (A) is 6, for B, the static variable is stored in the global data area, and sizeof calculates the size allocated in the stack, so sizeof (B) is 4; for C, for data alignment, the float size is 4, The int size is 4,char size 1, so sizeof (C) is 12.
Principle: In order to improve the storage speed of the CPU, VC has made the "alignment" processing for the starting address of some variables. By default, the VC rulesstart address where member variables are storedRelative toThe starting address of the structureThe offset must be a multiple of the number of bytes occupied by the variable's type.
Each member variable applies space in the order in which it appears in the structure, and adjusts the position according to the alignment above, and the empty byte VC is automatically populated. At the same time VC to ensure that the size of the structure of the structure of the number of bytes (that is, the structure of the maximum space occupied by the type of the number of bytes) , so after the last member variable to request space, also automatically fill the empty bytes as needed.
Each operating system has its own default memory alignment factor, and if it is a new version of the operating system, the default alignment factor is typically 8 because the operating system defines the maximum type of storage unit that is 8 bytes, such as Long long (why this must be done in the third section), There is no more than 8 bytes of type (for example, int is 4,char is 1,long at 32-bit compile time is 4, 64-bit compile time is 8). When the default alignment coefficients of the operating system conflict with the theory of memory alignment described in section I, the operating system's alignment factor is the baseline.
For example:
Assuming that the default alignment factor for the operating system is 4, then a variable of type long long does not satisfy the first section, meaning that a long long structure can be stored in a position divisible by 4 or stored in a position divisible by 8.
The default alignment factor for the operating system can be modified through the #pragma pack () statement, which is not recommended when writing a program, and is explained in section III
Example 2:
#include <stdio.h>
#pragma pack (4)
struct xx{
Char b;
Long Long A;
int C;
Char D;
};
#pragma pack ()
int main ()
{
struct XX BB;
printf ("&a =%p/n", &BB.A);
printf ("&b =%p/n", &bb.b);
printf ("&c =%p/n", &BB.C);
printf ("&d =%p/n", &BB.D);
printf ("sizeof (XX) =%d/n", sizeof (struct xx));
return 0;
}
Printing results are:
&a = Ffbff5e4
&b = Ffbff5e0
&c = Ffbff5ec
&d = ffbff5f0
sizeof (XX) = 20
Found a 8-byte, stored in a position that cannot be divisible by 8, stored in a position divisible by 4, the default alignment factor for the operating system is taken.
Three. Why the memory alignment occurs
Memory alignment is a strategy that the operating system takes to quickly access memory, simply to place two accesses to the variable. When accessing memory, the operating system reads a certain length each time (this is the default alignment factor for the operating system, or an integer multiple of the default alignment factor). If there is no memory alignment, the two accesses to the bus are generated in order to read a variable.
For example, assuming there is no memory alignment, the variable position of struct XX will appear as follows:
struct xx{
Char b; 0xffbff5e8
int A; 0xffbff5e9
int C; 0xffbff5ed
Char D; 0xffbff5f1
};
The operating system reads the 0XFFBFF5E8-0XFFBFF5EF memory first, then reads the 0XFFBFF5F0-0XFFBFF5F8 memory, in order to obtain the value C, needs to combine two sets of memory, consolidates, this greatly reduces the memory accesses the efficiency. (This involves the commonplace problem of space and efficiency which is more important?) No discussion here).
This allows you to understand why the first variable of a struct, regardless of its type, is divisible by 8 (since the access memory starts from an integer multiple of 8, in order to increase the efficiency of reading)!
The problem of memory alignment mainly exists in understanding the distribution of complex structures such as structs in memory.
The first thing to understand is the concept of memory alignment.
Many real computer systems restrict the location of basic types of data in memory, and they require that the value of the first address of the data be a multiple of a number k (usually 4 or 8), which is called memory alignment.
This k differs from one compiler to another under different CPU platforms. For example, 32-bit word-length computers and 16-bit word-length computers. This is a bit far from us. Our development involves two major platforms, Windows and Linux (Unix), and the compilers involved are primarily Microsoft compilers (such as CL), and GCC.
The purpose of memory alignment is to make the first address of each basic data type a multiple of the corresponding K, which is the ultimate magic weapon for understanding memory alignment. In addition, the differences between compilers are also distinguished. Understand that these two points are basically going to fix all the memory alignment issues.
K in different compilers:
1. For Microsoft compilers, the size of each base type is this K. In general, the char type is 8,int to 32,long and 32,double to 64.
2, for the GCC compiler under Linux, the specified size is less than or equal to 2, the K value is its size, greater than or equal to 4 is 4.
Understand that the above description of the structure and other composite structures of memory distribution should be very clear.
Let's look at the simplest type: Members in a struct are basic data types, for example:
struct TEST1
{
Char A;
Short B;
int C;
Long D;
Double E;
};
On the Windows platform, under Microsoft compilers:
Assuming that the 0 address starts, first the K value of a is 1, its first address can be arbitrary position, so a occupies the first byte, that is, address 0, then the K value of B is 2, his first address must be a multiple of 2, cannot be 1, so address 1 that byte is populated, B header address 2, Occupy address 2, 3; then to C, The k value of C is 4, his first address is a multiple of 4, so the first address is 4, occupies the address 4,5,6,7, and then to d,d the K value is also 4, so his first address is 8, occupying the address 8,9,10,11. Finally to E, his K value is 8, the first address is a multiple of 8, so address 12,13,14,15 is populated, his first address should be 16, occupy address 16-23. Obviously its size is 24.
This is the distribution of test1 in memory. We create a variable of type test1, A, B, C, D, E are assigned values 2, 4, 8, 16, 32 respectively. Then from the low address, print out the memory of each byte corresponding to the 16 binary number is:
2 0 4 0 8 0 0 0 10 0 0 0 0 0 0 0 0 0 0 0 0 0 40 40
Verify:
It is clear that the inference is correct.
On the Linux platform, under the GCC compiler:
Assuming that the 0 address starts, first the K value of a is 1, its first address can be arbitrary position, so a occupies the first byte, that is, address 0, then the K value of B is 2, his first address must be a multiple of 2, cannot be 1, so address 1 that byte is populated, B header address 2, Occupy address 2, 3; then to C, The k value of C is 4, his first address is a multiple of 4, so the first address is 4, occupies the address 4,5,6,7, and then to d,d the K value is also 4, so his first address is 8, occupying the address 8,9,10,11. Finally to E, starting here with the Microsoft compiler began to differ, his K value is not 8, is still 4, so its first address is 12, occupy address 12-19. Obviously its size is 20.
Verify:
We create a variable of type test1, A, B, C, D, E are assigned values 2, 4, 8, 16, 32 respectively. Then from the low address, print out the memory of each byte corresponding to the 16 binary number is:
2 0 4 0 8 0 0 0 10 0 0 0 0 0 0 0 0 0 40 40
Obviously the inference is also correct.
Next, take a look at a few special cases, in order to avoid trouble, no longer describe the memory distribution, only calculate the size of the structure.
The first type: nested structure
struct TEST2
{
Char F;
struct Test1 g;
};
On the Windows platform, under Microsoft compilers:
In this case, if the second member of the Test2 is taken apart to study the memory distribution, then you can know that the member F of Test2 occupies address 0, G.A occupy address 1, after the memory distribution is not changed, still meet all the basic data members of the first address for its corresponding to the principle of a multiple of K, then test2 size is still 24. But in fact the size of the test2 is 32, because: can not be changed because of the structure of test2 test1 memory distribution, so in order to make the Test1 species are still satisfied with the alignment requirements, F members need to fill a certain number of bytes behind, it is not difficult to find that the number should be 7, To ensure the alignment of the test1. So test2 increased by 8 bytes relative to Test1, so the size of the test2 is 32.
On the Linux platform, under the GCC compiler:
Similarly, if the second member of Test2 is taken apart to study the memory distribution, then you know that the member F of Test2 occupies address 0, G.A occupy address 1, after the memory distribution is not changed, still meet all the basic data members of the first address for its corresponding to the principle of a multiple of K, then test2 size is still 20. But in fact the size of the test2 is 24, the same is because: can not be changed because of the structure of test2 test1 memory distribution, so in order to make the Test1 species are still satisfied with the alignment requirements, F members need to fill a certain number of bytes behind, it is not difficult to find that the number should be 3, To ensure the alignment of the test1. So test2 increased by 4 bytes relative to Test1, so the size of the test2 is 24.
Second type: bit-segment alignment
struct TEST3
{
unsigned int a:4; A member of this struct uses a 32-bit 4 bit field, B uses 4 bits, two members share an int type, and a single integer length is used.
unsigned int b:4;
char c; 4 bytes
};
Or
struct TEST3
{
unsigned int a:4;
int b:4;
char c;
};
On the Windows platform, under Microsoft compilers:
Multiple contiguous numbers of the same type (signed and unsigned, as long as the basic type is the same, and the same number), they can be viewed as a whole if they occupy no more digits than the base type. The different types of numbers follow the respective alignment.
such as: Test3, A, B can be as a whole, they as an int data to view, so the size of the Test3 is 8 bytes. And the values of A and B are arranged in memory starting from the low, in the first 0-3 bits and 4-7 bits in the 4-byte region
If the TEST4 bit the following format
struct TEST4
{
unsigned int a:30;
unsigned int b:4;
char c;
};
Then the size of the Test4 is 12 bytes, and the values of A and B are distributed respectively in the first 30 bits of a 4 byte, and the second 4 bytes of the first 4 bits.
If TEST5 is the following form
struct TEST5
{
unsigned int a:4;
unsigned char b:4;
char c;
};
So because of the different types of int and char, they are aligned in their own way, so the size of the test5 should be 8 bytes, and the values of A and B are in the first 4 bits and the 5th byte of the top 4 bits, respectively.
On the Linux platform, under the GCC compiler:
struct TEST3
{
unsigned int a:4;
unsigned int b:4;
char c;
};
GCC, adjacent members, regardless of the type is the same, the sum of the number of digits than the first of these members of the size of the time, in the structure with a K value of 1 aligned, outside the structure K value is its base type value. Do not exceed in the case of in-memory sequence.
such as TEST3, its size is 4. The value of a, B, in memory, is sequentially ranked in the first four bytes of 0-3 and 4-7 bits.
If the TEST4 bit the following format
struct TEST4
{
unsigned int a:20;
unsigned char b:4;
char c;
};
The size of the Test4 is 4 bytes, and the values of A and B are distributed in the first 4 bytes of 0-19 bits, and 20-23 bits, and c is stored in the 4th byte.
If TEST5 is the following form
struct TEST5
{
unsigned int a:10;
unsigned char b:4;
Short C;
};
Then the size of the test5 should be 4 bytes, the value of A/b is 0-9-bit and 10-13-bit. c is stored in the second two bytes. If the size of a becomes 20,
Then the size of the test5 should be 8 bytes. That
struct TEST6
{
unsigned int a:20;
unsigned char b:4;
Short C;
};
At this time, Test6 A, B occupies a total of 3 bytes of 0,1,2, C, the K value is 2, in fact, can be 4-bit the first position, but outside the structure, a to be in the way of int alignment. That is to say that two consecutive Test6 objects are stored in memory, the first place of a is guaranteed to be a multiple of 4, then C must be filled with more than 2 bits. So the size of the Test6 is 8 bytes.
Memory alignment-Small building a night to listen to the Spring Rain-blog Park
Http://www.cnblogs.com/kex1n/archive/2009/06/16/2286527.html
Structure and class memory allocation-bit accumulation-Sohu Blog
Http://lukas06.blog.sohu.com/84854461.html
C Language Memory alignment-winlin-Blog channel-csdn.net
http://blog.csdn.net/pcliuguangtao/article/details/6219427
Memory completion sequence One: about memory alignment and padding