In the C language, the structure is a composite data type, and its components can be both variables of basic data types (such as int, long, float, and so on, it can also be a data unit of a composite data type (such as an array, structure, and union. In the structure, the compiler allocates space for each member of the structure based on its natural alignment condition. Each member is stored in the memory in the declared order. The address of the first member is the same as that of the entire structure. For example, the following structure shows the allocation of member spaces:
Struct test
{
Char x1;
Short x2;
Float x3;
Char x4;
};
The first member of the structure, x1, is of the char type. Its natural interface is 1, and its offset address is 0, occupying 1st bytes. The second member x2 is of the short type, and its natural interface is 2. The starting address must be a 2-byte peer. Therefore, the compiler fills a Null Byte between x2 and x1. The third member x3 and fourth member x4 of the structure exactly fall on their natural peer address, and no additional bytes are needed before them. In the test structure, the x3 member requires a 4-byte bounded boundary and is the maximum boundary unit required by all the members of the structure. Therefore, the natural boundary condition of the test structure is 4 bytes, the compiler fills in three NULL bytes after Member x4. The entire structure occupies 12 bytes of space.
Change the default byte alignment of the C Compiler
By default, the C compiler allocates space for each variable or data unit based on its natural limitations. Generally, you can use the following method to change the default peer condition:
· With the pseudo command # pragma pack (n), the C compiler will align according to n Bytes.
· Use the pseudo command # pragma pack () to cancel the custom byte alignment.
In addition, the following method is provided:
· _ Attribute (aligned (n) to align the structure members to the natural boundary of n Bytes. If the length of a member in the structure is greater than n, the maximum member length is used for alignment.
· _ Attribute _ (packed): cancels the optimization alignment of the structure during compilation and alignment according to the actual number of bytes occupied.
The first method above n = 1, 2, 4, 8, 16... is more common.
Http://blog.csdn.net/wenddy112/articles/300583.aspx
Application Instance
In network protocol programming, data packets of different protocols are often processed. One way is to get various information through the pointer offset method, but this method is not only complicated in programming, but also troublesome to modify the program once the Protocol changes. After learning about the compiler's allocation principles for the structure space, we can use this feature to define our own protocol structure and obtain various information by accessing the structure members. In this way, not only programming is simplified, but even if the protocol changes, we only need to modify the definition of the protocol structure. Other programs do not need to be modified, saving time and effort. The following uses the TCP protocol header as an example to describe how to define the protocol structure. The protocol structure is defined as follows:
# Pragma pack (1) // align in 1 byte mode
Struct TCPHEADER
{
Short SrcPort; // 16-bit source port number
Short DstPort; // 16-bit destination port number
Int SerialNo; // 32-bit serial number
Int AckNo; // 32-bit confirmation number
Unsigned char HaderLen: 4; // 4-bit Header Length
Unsigned char Reserved1: 4; // retain four of the six digits
Unsigned char Reserved2: 2; // retain two of the six digits
Unsigned char URG: 1;
Unsigned char ACK: 1;
Unsigned char PSH: 1;
Unsigned char RST: 1;
Unsigned char SYN: 1;
Unsigned char FIN: 1;
Short WindowSize; // 16-bit window size
Short TcpChkSum; // 16-bit TCP check
Short UrgentPointer; // 16-bit emergency pointer
};
# Pragma pack () // cancel the 1-byte alignment
The following is a hot question discussed at the CSDN Forum:
# Pragma pack (8)
Struct s1 {
Short;
Long B;
};
Struct s2 {
Char c;
S1 d;
Long e;
};
# Pragma pack ()
Question
1. sizeof (s2) =?
2. How many bytes are left behind c in s2 and then d?
The result is as follows:
The sizeof (S2) result is 24.
An important condition for member alignment is that each member is aligned separately. That is, each member is aligned in its own way.
That is to say, although alignment by 8 bytes is specified above, not all Members are alignment by 8 bytes. the alignment rule is that each member has a smaller alignment according to its type alignment parameter (usually the size of this type) and the specified alignment parameter (8 bytes here. in addition, the length of the structure must be an integer multiple of all alignment parameters used.
In S1, member a is 1 byte, which is aligned by 1 byte by default, and the specified alignment parameter is 8. Among the two values, 1 and a are aligned by 1 byte. Member B is 4 bytes, the default value is 4-byte alignment. In this case, it is 4-byte alignment, so sizeof (S1) should be 8;
In S2, c is the same as a in S1. It is aligned by 1 byte, while d is a structure. It is 8 bytes. What is its alignment? For the structure, its default alignment is the largest of all its members using alignment parameters, and S1 is 4. therefore, member d is aligned in 4 bytes. the member e is 8 bytes, which is aligned by 8 bytes by default. It is the same as the specified one, so it is connected to the boundary of 8 bytes. At this time, 12 bytes are used, therefore, four bytes are added, and the member e is placed starting from 16th bytes. at this time, the length is 24 and can be divisible by 8 (member e is aligned by 8 bytes. in this way, a total of 24 bytes are used.
A B
Memory layout of S1: 11 **, 1111,
C S1.a S1. B d
Memory layout of S2: 1 ***, 11 ***, 1111, *** 11111111
There are three important points:
1. Each Member is aligned in its own way, and the length can be minimized.
2. The default alignment of complex types (such as structures) is the alignment of its longest member, so that the length can be minimized when the member is a complex type.
3. The alignment length must be an integer multiple of the largest alignment parameter in the member. This ensures that each item is bounded when processing arrays.
In addition, for arrays, alignment is the alignment of elements. For example:
Char a [3]; in this way, its alignment is the same as writing three char, that is, it is still aligned by 1 byte.
If you write: typedef char Array3 [3];
The alignment of Array3 type is still aligned by 1 byte, rather than by its length.
Whatever the type, the alignment boundary must be 1, 2, 4, 8, 16, 32, 64.
Struct s1
{
Char a [8];
};
Struct s2
{
Double d;
};
Struct s3
{
S1 s;
Char;
};
Struct s4
{
S2 s;
Char;
};
Cout <sizeof (s1) <endl; // 8
Cout <sizeof (s2) <endl; // 8
Cout <sizeof (s3) <endl; // 9
Cout <sizeof (s4) <endl; // 16;
The size of s1 and s2 is 8, but the alignment of s1 is 1 and s2 is 8 (double). Therefore, this difference exists in s3 and s4.
Therefore, when you define a struct, if the space is insufficient, consider alignment to arrange the elements in the struct.
Union alignment: it is the largest alignment among members. The length is the length obtained by adjusting the longest member according to this alignment.
Union u
{
Double;
Int B;
};
Union u2
{
Char a [13];
Int B;
};
Union u3
{
Char a [13];
Char B;
};
Cout <sizeof (u) <endl; // 8
Cout <sizeof (u2) <endl; // 16
Cout <sizeof (u3) <endl; // 13
We all know that the size of union depends on the size of one member that occupies the largest space among all its members. So for u, the size is the largest double type member a, so sizeof (u) = sizeof (double) = 8. However, for u2 and u3, the maximum space is an array of char [13] type. Why is the size of u3 13 and that of u2 16? The key lies in the member int B in u2. Because of the existence of int type members, the u2 alignment is changed to 4. That is to say, the u2 size must be 4 to the world, therefore, the occupied space is changed to 16 (the nearest 13 peer ).
Conclusion: The alignment of composite data types, such as union, struct, and class, is the alignment of the members with the largest alignment.
By the way, the 32 C ++ uses eight-bit bounds to increase the running speed. Therefore, the compiler tries its best to put the data in the world to improve the memory hit rate. The field can be changed. The # pragmapack (x) macro can be used to change the method of the compiler's field. The default value is 8. C ++ is a smaller method than its own size. For example, if you specify that the compiler is bounded by 2 pairs and the size of the int type is 4, the int pair is bounded by 2 and 2, which is smaller than 4. In the default method, because almost all data types are not greater than the default method 8 (except longdouble ), therefore, all inherent types of peer methods can be considered as the size of the type itself. Www. Change the above program:
# Pragmapack (2)
Union u2
{
Char a [13];
Int B;
};
Union u3
{
Char a [13];
Char B;
};
# Pragmapack (8)
Cout <sizeof (u2) <endl; // 14
Cout <sizeof (u3) <endl; // 13
Because the method of Manually changing to 2 is also changed to 2 for int, and the biggest Member for u2 is 2, so now sizeof (u2) = 14.
Conclusion: C ++'s inherent type of bounded access Compiler's bounded access method is smaller than its own size.
This article from the CSDN blog, reproduced please indicate the source: http://blog.csdn.net/digu/archive/2009/11/04/4768623.aspx