Structure byte alignment

Source: Internet
Author: User

Structure byte alignment

When we use the sizeof operator to calculate the space occupied by a struct, we do not simply add the space occupied by all elements in the struct. This involves the issue of memory byte alignment. Theoretically, access to any variable can start from any address, but in fact it is not. In fact, access to a specific type of variable can only be accessed at a specific address, in this case, variables need to be arranged according to certain rules in space rather than simply in order. This is memory alignment.

The Data Alignment issue must be discussed when calculating the size of Structure Variables.In order to make the CPU Access faster (this is related to the number of CPU operations), c ++ often calculates the size of members in the Structure Variable in multiples of 4 or 8 when processing data, this is called data alignment ). This may waste some memory, but theoretically the CPU speed is faster.

Reason for memory alignment:

1)Some platforms can only access specific types of data at specific addresses;

2)Improves data access speed. For example, some platforms read data from even addresses each time. For an int-type variable, if it is stored in an even address unit, the variable can be read in only one read period; however, if the variable is stored in an odd address unit, two read cycles are required to read the variable.

In the c99 standard, the details of memory alignment are not described much. The specific implementation is handled by the compiler. Therefore, the memory alignment may be slightly different in different compiling environments, but the most basic principle of alignment is consistent.

ForByte alignment of structThere are two main points:

1)The offset of each member of the struct to the first address of the struct is the alignment parameter (In this sentenceAlignment ParametersIs to take the alignment parameter of each variable and the default alignment parameter # A smaller value in Pragma pack (n)Is an integer multiple of, if necessary, the bytes are filled between members.. When the compiler opens a space for a struct member, it first checks whether the offset of the preopened space address to the first address of the struct is an integer multiple of the alignment parameter. If yes, It stores the member. If not, then fill in several bytes to meet the requirements of integer times.

2)The size of the space occupied by struct variables is an alignment parameter (It is an integer multiple of the size of the alignment parameter of all variables in the struct and the default alignment parameter # pragma pack (n.If necessary, several bytes will be filled at the end of the last member so that the occupied space is an integer multiple of the size of the alignment parameter.

Note: Before reading these two principles, you should first understand the concept of alignment parameters. Each variable has its own alignment parameter, which is different in different compiling environments. The following lists the Alignment Parameters of various types of variables in the two most common compiling environments.

1.Memory alignment is related to compiler settings. First, you need to know the default value of the compiler.

2.If you do not want to use the default compiler, you can use# Pragma pack (N)To specifyNAlignment

3.Alignment of each struct variable, if alignment ParameterN (By defaultPragmaSpecify)Greater than the number of bytes occupied by the variable(M), Then followMAlignment. The address after memory offset isMOtherwiseNAlignment. The address after memory offset isN. That is, the minimum length rule.

4.Total struct size: The alignment length must be an integer multiple of the largest Alignment Parameters in the member. The maximum alignment parameter is obtained in step 3.

5.Supplement:If the structAAnd structB, ThenBThe alignment of is to select itLongestAlignment of members

Therefore, it takes three steps to calculate the struct size. First, it is determined that the currentProgramAligned by number(Reference1,2Point)And then calculate the size and offset of each struct variable.(Reference3,5)Finally, calculate the total size of the struct (refer4).

 

 

From the above, we can find that the alignment parameters of various types of variables in Windows (32)/vc6.0 are the size of the bytes occupied by these types of variables, while in Linux (32) /The alignment parameter of the double type variable in GCC is 4, because in Linux (32)/GCC, if the length of the variable of this type does not exceed the CPU length, the length of a variable of this type is used as its own alignment parameter. If the length of a variable of this type exceeds the CPU character length, the alignment parameter itself is the CPU character length, while the CPU character length of a 32-bit system is 4, therefore, the variable alignment parameter of the double type in Linux (32)/GCC is 4. If it is in Linux (64), the alignment parameter of the double type is 8.

In addition to the variable's own alignment parameter, there is also an alignment parameter, that is, the default alignment parameter # pragma pack (n) for each compiler. This value can be passed throughCodeIf no value is set, the default value is used. In Windows (32)/vc6.0, the value of N can be 1, 2, 4, or 8. The default value is 8. In Linux (32)/GCC, N can be set to 1, 2, or 4, and 4 by default. Note that values of N in windows, such as Dev-CPP and mingw, are the same as those in VC.

After understanding these two concepts, you can understand the above two principles. For the first principle, the offset of each variable to the first address of the struct must be an integer multiple of the alignment parameter.Alignment ParametersIt is a small value of the alignment parameter of each variable and the default alignment parameter # pragma pack (n.For example, if the struct a contains the int a variable, the alignment parameter of A is 4 (the environment is Windows/VC), and the default alignment parameter of VC is 8, if the value is smaller, the offset of A to the starting address of struct a must be a multiple of 4.

For the second principle, the size of the space occupied by the struct variable is an integer multiple of the alignment parameter. The alignment parameters in this sentence are a bit complicated,It compares the maximum value of the alignment parameter of all variables in the struct with the default alignment parameter # pragma pack (N). Smaller values are used as alignment parameters.For example, if two variables int A and double B are defined in struct a, the alignment parameter of variable A is 4, and # pragma pack (N) if the default value is 8, the alignment parameter of A is 4. The alignment parameter of B is 8, and the default value of # pragma pack (n) is 8, then the alignment parameter of B is 8. Because the final alignment parameter of A is 4 and the final alignment parameter of B is 8, the larger of the two are 8, and then compare them with # pragma pack (n, the smaller part is used as the alignment parameter, that is, 8, which means that the final size of the struct must be divisible by 8.

The following is a test example:

Note: The test results in the following example are all tested in Windows (32)/VC. The default alignment parameter is 8.


# Include <iostream>
Using namespace STD;
// # Pragma
Pack (4)
// Set 4-byte alignment
// # Pragma
Pack ()
// Cancel the 4-byte alignment


Typedef struct node1
{
Int;
Char
B;
Short
C;
} S1;

Typedef struct node2
{
Char
A;
Int B;
Short
C;
} S2;

Typedef struct node3
{
Int;
Short
B;
Static int
C;
} S3;

Typedef struct node4
{
Bool
A;
S1 S1;
Short
B;
} S4;

Typedef struct node5
{
Bool
A;
S1 S1;
Double
B;
Int C;
} S5;

Int main (INT argc, char * argv [])
{

Cout <sizeof (char) <"
"<Sizeof (short) <"
"<Sizeof (INT) <"
"<Sizeof (float) <"
"<Sizeof (double) <Endl;

S1 S1;
S2;
S3 S3;
S4;
S5 S5;

Cout <sizeof (S1) <"
"<Sizeof (S2) <"
"<Sizeof (S3) <"
"<Sizeof (S4) <"
"<Sizeof (S5) <Endl;

Return
0;
}

The following describes the allocation of several struct bytes.

For example, for node2

 
TypedefStructNode2 {CharA;IntB;ShortC;} S2;

Sizeof (S2) = 12;

For variable A, its own alignment parameter is 1, # The default value of Pragma pack (n) is 8, then the alignment parameter of A is 1, and 1 byte space is allocated to it, its offset relative to the starting address of the struct is 0, which can be divisible by 4;

For variable B, its own alignment parameter is 4, # The default value of Pragma pack (n) is 8, then the alignment parameter of final B is 4, the offset of the following address to the starting address of the struct is, which cannot be divisible by 4. Therefore, we need to fill 3 bytes behind a to make the offset reach 4, and then allocate 4 bytes of space for B;

For variable C, its own alignment parameter is 2, # The default value of Pragma pack (n) is 8, then the alignment parameter of final C is 2, the offset of the next address to the starting address of the struct is 8, which can be divided by 2. Therefore, C is allocated 2 bytes of space.

At this time, the number of bytes occupied by the struct is 1 + 3 + 4 + 2 = 10 bytes.

Finally, because the final alignment parameters of A, B, and C are, 2, and the maximum value is 4, # The default value of Pragma pack (n) is 8, the final size of the struct variable must be divisible by 4. However, 10 cannot be divisible by 4, so it is necessary to fill 2 bytes to 12 bytes later. Its storage is as follows:

| Char | ---- | 4 bytes

| -------- Int -------- | 4 bytes

| -- Short -- | ---- | 4 bytes

12 bytes in total

For node3, it contains static data members.

 
TypedefStructNode3 {IntA;ShortB;Static IntC;} S3;

 

Sizeof (S3) = 8. Here the struct contains static data members, while the storage location of static data members (Static variables are stored in the global data zone, and the size allocated in the sizeof computing stack is not included.) Is irrelevant to the storage address of the struct instance (note that only the struct in C ++ can contain static data members, while the struct in C cannot contain static data members ). The memory storage method is as follows:

| -------- Int -------- | 4 bytes

| -- Short-| ---- | 4 bytes

The variable C is stored in the static data zone separately. Therefore, siezof is used to calculate the space occupied by C in an hour.

For node5, it contains struct variables.

TypedefStructNode5 {BoolA; S1 S1;DoubleB;IntC;} S5;

 

Sizeof (S5) = 32.

For variable A, the alignment parameter is 1, # pragma pack (n) is 8, then the final alignment parameter of A is 1, allocating 1 byte space to it, its offset relative to the starting address of the struct is 0, which can be divisible by 1;

For S1, its own alignment parameter is 4 (For a struct variable, its own alignment parameter is the maximum value of the final alignment parameter of each variable in it.), # Pragma pack (n) is 8, soThe final alignment parameter of S1 is 4,The offset of the next address relative to the starting address of the struct is 1 and cannot be fully divided by 4. Therefore, we need to fill 3 bytes behind a to reach 4 and allocate 8 bytes of space for it;

For variable B, its own alignment parameter is 8, # The default value of Pragma pack (n) is 8, then the final alignment parameter of B is 8, the offset of the next address to the starting address of the struct is 12 and cannot be divisible by 8. Therefore, we need to fill in 4 bytes after S1 to 16 and allocate 8 bytes of space for B;

For variable C, its own alignment parameter is 4, # The default value of Pragma pack (n) is 8, then the final alignment parameter of C is 4, next, the offset relative to the actual address of the struct is 24, which can be fully divided by 4. Therefore, a 4-byte space is allocated directly to C.

The number of bytes occupied by the struct is 1 + 3 + 8 + 4 + 8 + 4 = 28 bytes.

For the entire struct, the final alignment parameters of each variable are, and the maximum value is 8. # The default value of Pragma pack (n) is 8, therefore, the final struct size must be a multiple of 8. Therefore, the size of the final struct must be 4 bytes at the end to 32 bytes. Its storage is as follows:

The S5 memory allocation should be as follows:
| -------- Bool -------- | 4 bytes
| --------- S1 --------- | 4 bytes
| --------- S1 --------- | 4 bytes
| --------------------- | Empty output
| -------- Double ----- | 8 bytes
| ---- Int ---- | --------- | 8 bytes

In addition, it can be explicitly used in the Program # pragma
Pack (n) is used to set the default alignment parameters of the system. After the display settings, the set value is used as the standard. Other settings are similar to those described above and will not be repeated, you can test it on your own. To cancel the setting, use # pragma
Pack () to cancel.


The length of a struct must be an integer multiple of the longest data element.


The general principle of CPU optimization rules is as follows: for n-byte elements (n = 2, 4, 8 ,...), the first address can be divisible by N to obtain the best performance.


This type of question is not about understanding the language itself and compiler, but about the applicant's understanding of the underlying mechanism of the computer and the principles of program design. That is to say, if you want to design the compiler, how will you solve the memory alignment problem.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.