Is that okay?
Copy Code code as follows:
#include <iostream>
using namespace Std;
struct TEST_A
{
Char A;
Char b;
int C;
};
struct TEST_B
{
Char A;
int C;
Char b;
};
struct Test_c
{
int C;
Char A;
Char b;
};
int main ()
{
struct Test_a A;
memset (&a, 0, sizeof (a));
struct Test_b B;
memset (&b, 0, sizeof (b));
struct Test_c C;
memset (&c, 0, sizeof (c));
Print the memory size of the struct
Cout<<sizeof (a) <<endl;
Cout<<sizeof (b) <<endl;
Cout<<sizeof (c) <<endl;
return 0;
}
OK, a simple program, what is the output of the program above? If you understand, you will know what I am going to say, I can skip it, if you don't know, or are still vague, please read on.
Why is that?
The output of the above program is as follows (Windows 8.1 + Visual Studio Update3):
Copy Code code as follows:
Print the memory size of the struct
cout<< sizeof (a) <<endl; 8bytes
cout<< sizeof (b) <<endl; 12bytes
cout<< sizeof (c) <<endl; 8bytes
Is that weird? The definition of the three structures, just a change in the structure of the members defined in order, how the resulting structure of the memory size is not the same? Is that weird? Well, that's the memory alignment concept I'm going to summarize here.
Snap to memory
The problem of memory alignment mainly exists in the understanding of the distribution of composite structures such as struct and union in memory. Many actual computer systems have a limit on the location of the underlying type 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 the so-called memory alignment. This value K under different CPU platform, different compiler performance also different, now we are involved in the mainstream compiler is Microsoft's compiler and GCC.
For our top-tier programmers, it's really rare to consider the problem of memory alignment, which is "transparent" to top programmers. Memory alignment, it can be said that the compiler does the work, the compiler for each piece of data in the program in the appropriate memory location. Most of the time we have to write more efficient code, and we need to understand the concept of this memory alignment and what the compiler is doing behind the back. Especially for C and C + + programmers, understanding and mastering memory alignment is more important.
Why should there be memory alignment? How much memory to occupy, then open up the corresponding size of the memory is good, like the above structure, two char type and an int type, size should be 6bytes to Ah, how is 8bytes, is 12bytes ah? For memory alignment, the main purpose is to improve the performance of the program, data structure, especially the stack, should be as far as possible on the natural boundary alignment. The reason is that the processor needs to do two memory accesses in order to access memory that is not on it, but the aligned memory access requires only one memory access.
In computers, words, double words, and four words do not need to be aligned in memory on natural boundaries (for words, double words, and four words, the natural boundaries are even addresses, which can be divisible by 4 addresses and addresses that can be divisible by 8). If a word or two-word operand crosses a 4-byte boundary, or a four-word operand crosses 8-byte boundaries, it is considered misaligned, which requires two bus cycles to access memory. A word starting address is an odd number, but not across a word boundary, is considered to be justified, can be accessed in a bus cycle. To sum up, memory alignment can be summed up in one sentence--data items can only be stored in a memory location where the address is an integer multiple of the size of the data item.
Let's take a look at an example of a simple answer:
Copy Code code as follows:
#include <stdio.h>
struct Test
{
Char A;
int b;
int C;
Char D;
};
int main ()
{
struct Test structtest;
printf ("&a=%p\n", &STRUCTTEST.A);
printf ("&b=%p\n", &structtest.b);
printf ("&c=%p\n", &structtest.c);
printf ("&d=%p\n", &STRUCTTEST.D);
printf ("sizeof (Test) =%d\n", sizeof (structtest));
return 0;
}
The output results are as follows:
Copy Code code as follows:
&a=00c7fa44
&b=00c7fa48
&c=00c7fa4c
&d=00c7fa50
sizeof (Test) =16
The member variable b of the struct test uses a byte number of 4bytes, so it can only be stored in the position of 4 integer times, because a is only 11 bytes, and A's address 00c7fa44 and B's address 00c7fa48 between 4bytes, which means that a actually occupies 4 bytes, This ensures that the starting address for B is an integer multiple of 4. This is the memory alignment. If there is no memory alignment, we'll take the above code as an example, and the results might be as follows:
Copy Code code as follows:
&a=ffbff5e8
&b=ffbff5e9
&c=ffbff5ed
&d=ffbff5f1
sizeof (Test) =10
As you can see, a occupies a byte, followed by a B, and before that, memory alignment is a strategy used by the operating system to quickly access memory, simply to prevent two of accesses to a variable. When the operating system accesses memory, it reads a certain length each time (this is the operating system's default alignment factor, or an integer multiple of the default alignment factor). Without the memory alignment, when we read the variable C, read the 0XFFBFF5E8~0XFFBFF5EF memory for the first time, read the 0xffbff5f0~0xffbff5f8 memory for the second time, because the memory occupied by variable C spans two address areas, in order to get the value of the variable C correctly , you need to read two times and consolidate two memory merges, which reduces the efficiency of memory access.
I've said so much here, and I'm pretty wrapped around the mouth, and that's the rule of memory alignment. In C + +, each compiler on a particular platform has its own memory alignment rules, and here we summarize the rules for memory alignment.
Memory Alignment Rules
Compilers on each particular platform have their own default alignment coefficients. We can change this factor by precompiling the command #pragma pack (k), where K is the "alignment factor" that needs to be specified, or by using #pragma pack () to cancel the custom byte alignment. The specific alignment rules are as follows:
Rule 1:struct or Union data member alignment rule: The first data member is placed where the offset is 0, and alignment is aligned according to the numeric value specified by the #pragma pack and the number of bytes that are smaller in itself;
Copy Code code as follows:
#pragma pack (4)//Specify an alignment factor of 4, and when the byte count is greater than or equal to 4 o'clock, align according to 4
struct Test
{
Char X1;
Short X2;
Float X3;
Char x4;
};
The X1 occupies a byte number of 1,1 < 4 and is aligned according to the alignment factor 1, so the X1 is placed at the offset 0 position;
The X2 occupies a byte number of 2,2 < 4 and is aligned according to the alignment factor 2, so x2 is placed at offset 2,3 position;
The X3 occupies a byte number of 4, 4 = 4, is aligned according to the alignment factor 4, so the X3 is placed in the position of offset 4,5,6,7;
The X4 occupies a byte number of 1,1 < 4 and is aligned according to the alignment factor 1, so the X4 is placed at the offset 8 position;
It's now 9bytes of memory, but actually measured in Visual Studio 2012 as 12bytes, why? Look at the next rule.
Rule 2:struct or union's overall alignment rule: After the data member completes the respective alignment, the struct or union itself is aligned, and the alignment follows the #pragma The number specified in the pack is performed in the struct or the smaller of the maximum data member length in the Union;
Continue to use Rule 1 examples to explain, according to rule 1 understanding, struct test has taken up 9bytes, the actual why is 12bytes? According to Rule 2, after all member alignment is complete, the struct or union itself is aligned; we set the alignment factor to 4, and struct test takes the largest number of bytes in the float type X3, because the X3 occupies a byte number less than or equal to the set alignment factor of 4, So the struct or union whole needs to be aligned according to 4bytes, which means that the number of bytes struct or union must be divisible by 4, OK. struct test has taken up 9bytes, 10bytes cannot be divisible by 4, 11bytes is not, 12bytes is right; therefore, struct test eventually occupies the number of bytes 12bytes.
The two rules above are the basic rules for memory alignment, which are locally aligned and then overall aligned.
Example analysis
summed up so many rules, do not point to the actual code, the total feel less what, OK. The following is a summary of the memory alignment rules for some actual code analysis (note: Test environment Windows 8.1 + Visual Studio update 3).
Test the code as follows, first confirm the test environment:
Copy Code code as follows:
#include <iostream>
using namespace Std;
struct Test
{
Char X1;
Double X2;
Short X3;
float x4;
Char X5;
};
int main ()
{
cout<< "sizeof (char)" <<sizeof (char) <<endl; 1byte
cout<< "sizeof (short)" <<sizeof (short) <<endl; 2bytes
cout<< "sizeof (int)" <<sizeof (int) <<endl; 4bytes
cout<< "sizeof (Double)" <<sizeof (double) <<endl; 8bytes
return 0;
}
I set up #pragma pack (k) separately and k=1,2,4,8,16 for testing.
Copy Code code as follows:
#pragma pack (1)//Set alignment factor to 1
struct Test
{
Char X1;
Double X2;
Short X3;
float x4;
Char X5;
};
First, use Rule 1 to align the member variables:
X1 <= 1, aligned according to 1, X1 occupy 0;
x2 > 1, aligned according to 1, X2 occupied 1,2,3,4,5,6,7,8;
x3 > 1, aligned according to 1, X3 occupy 9, 10;
x4 > 1, aligned according to 1, X4 occupied 11,12,13,14;
X5 > 1, aligned according to 1, X5 occupy 15;
Finally, rule 2 is used to align the struct as a whole:
X2 occupies the largest memory, for 8bytes,8bytes > 1byte, so the whole is aligned according to 1; 16%1=0.
So, in the case of the #pragma pack (1), struct test takes up 16bytes of memory; memory footprint as shown in the following figure:
Copy Code code as follows:
#pragma pack (2)//Set alignment factor to 2
struct Test
{
Char X1;
Double X2;
Short X3;
float x4;
Char X5;
};
First, use Rule 1 to align the member variables:
X1 <= 2, aligned according to 1, X1 occupy 0;
x2 > 2, aligned according to 2, X2 occupied 2,3,4,5,6,7,8,9;
X3 >= 2, aligned according to 2, X3 occupied 10, 11;
x4 > 2, aligned according to 2, X4 occupied 12,13,14,15;
X5 < 2, aligned according to 1, X5 occupy 16;
Finally, rule 2 is used to align the struct as a whole:
X2 occupies the largest memory, for 8bytes,8bytes > 2byte, so the overall alignment according to 2; 17%2!=0
So, in the case of the #pragma pack (2), struct test takes up 18bytes of memory; memory footprint as shown in the following figure:
Copy Code code as follows:
#pragma pack (4)//Set alignment factor to 4
struct Test
{
Char X1;
Double X2;
Short X3;
float x4;
Char X5;
};
First, use Rule 1 to align the member variables:
X1 <= 4, aligned according to 1, X1 occupy 0;
x2 > 4, aligned according to 4, X2 occupied 4,5,6,7,8,9,10,11;
x3 < 4, aligned according to 2, X3 occupy 12, 13;
X4 >= 4, aligned according to 4, X4 occupy 16,17,18,19;
X5 < 4, aligned according to 1, X5 occupy 20;
Finally, rule 2 is used to align the struct as a whole:
X2 occupies the largest memory, for 8bytes,8bytes > 4byte, so the overall alignment according to 4; 21%4!=0
So, in the case of the #pragma pack (4), struct test takes up 24bytes of memory; memory footprint as shown in the following figure:
Copy Code code as follows:
#pragma pack (8)//Set alignment factor to 8
struct Test
{
Char X1;
Double X2;
Short X3;
float x4;
Char X5;
};
First, use Rule 1 to align the member variables:
X1 <= 8, aligned according to 1, X1 occupy 0;
X2 >= 8, aligned according to 8, X2 occupy 8,9,10,11,12,13,14,15;
X3 < 8, aligned according to 2, X3 occupy 16, 17;
X4 <= 8, aligned according to 4, X4 occupy 20,21,22,23;
X5 < 8, aligned according to 1, X5 occupy 24;
Finally, rule 2 is used to align the struct as a whole:
X2 occupy the largest memory for the 8bytes,8bytes >= 8byte, so the overall alignment according to 8; 25%8!=0
So, in the case of the #pragma pack (8), struct test takes up 32bytes of memory; memory footprint as shown in the following figure:
Copy Code code as follows:
#pragma pack (16)//Set alignment factor to 16
struct Test
{
Char X1;
Double X2;
Short X3;
float x4;
Char X5;
};
First, use Rule 1 to align the member variables:
X1 < 16, aligned according to 1, X1 occupy 0;
X2 < 16, aligned according to 8, X2 occupied 8,9,10,11,12,13,14,15;
X3 < 16, aligned according to 2, X3 occupy 16, 17;
X4 < 16, aligned according to 4, X4 occupied 20,21,22,23;
X5 < 16, aligned according to 1, X5 occupy 24;
Finally, rule 2 is used to align the struct as a whole:
X2 occupy the largest memory for the 8bytes,16bytes >= 8byte, so the overall alignment according to 8; 25%8!=0
So, in the case of the #pragma pack (16), struct test takes up 32bytes of memory; memory footprint as shown in the following figure:
Summarize
Through the above example analysis, I have a comprehensive understanding of the memory alignment. Now come back and look at the code at the beginning of the article, the problem is solved, and through this code, let us recognize that the definition of struct or union, is also explained. In the future coding career, is it necessary to consider some more? Tangle ~