#pragma pack (n)

In the C language, a structure is a composite data type, and its constituent elements can be either variables of basic data types (such as int, long, float, etc.), or some composite data types (such as arrays, structures, unions, etc.) data unit. In a structure, the compiler allocates space for each member of the structure according to its natural alignment. Members are stored sequentially in memory in the order in which they are declared, and the address of the first member is the same as the address of the entire structure.

For example, the space allocation of each member of the following structure:
struct test 
{
     char x1;
     short x2;
     float x3;
     char x4;
};

    The first member of the structure, x1, whose offset address is 0, occupies the first byte. The second member x2 is of type short, and its starting address must be a 2-byte pair, so the compiler fills a null byte between x2 and x1. The third member x3 and the fourth member x4 of the structure fall exactly on their natural opposite addresses, and no additional padding bytes are required in front of them. In the test structure, the member x3 requires a 4-byte boundary, which is the largest boundary unit required among all members of the structure. Therefore, the natural boundary condition of the test structure is 4 bytes, and the compiler fills 3 bytes after the member x4. Null bytes. The space occupied by the entire structure is 12 bytes.

Changing the C compiler's default byte alignment By
    default, the C compiler allocates space for each variable or data unit according to its natural boundary conditions. In general, the default alignment conditions can be changed in the following ways:
     · Using the directive #pragma pack (n), the C compiler will align to n bytes.
     · Use the directive #pragma pack () to cancel the custom byte alignment.

In addition, there is one of the following ways:
     · __attribute((aligned (n))), so that the structure members acted on are aligned on the natural boundary of n bytes. If there are members in the structure whose length is greater than n, they are aligned according to the length of the largest member.
     __attribute__ ((packed)), cancel the optimized alignment of the structure during compilation, and align it according to the actual number of bytes occupied.

The above n = 1, 2, 4, 8, 16... The first way is more common.

#pragma pack (8)

struct s1{
short a;
long b;
};

struct s2{
char c;
s1 d;
long long e;
};

#pragma pack ()

Question 
1. sizeof(s2) = ?
2. How many bytes are left after c in s2, followed by d?

The result is as follows:

The result of sizeof(S2) is 24.
    Member alignment has an important condition, that is, each member is aligned separately. That is, each member is aligned in its own way. That is to say, although 8-byte alignment is specified above, not all The members are aligned with 8 bytes. The alignment rule is that each member is aligned according to the smaller of the alignment parameter of its type (usually the size of this type) and the specified alignment parameter (here 8 bytes) .And the length of the structure must be an integer multiple of all the alignment parameters used, if it is not enough, fill up with empty bytes.
    In S1, member a is 1 byte aligned by 1 byte by default, and the specified alignment parameter is 8. These two values Take 1, a is aligned by 1 byte; member b is 4 bytes, the default is aligned by 4 bytes, then it is aligned by 4 bytes, so sizeof(S1) should be 8;
    in S2, c and Like a in S1, it is aligned by 1 byte, and d is a structure, it is 8 bytes, what is it aligned by? For a structure, its default alignment is the alignment parameter used by all its members. The largest one , S1 is 4. Therefore, member d is aligned by 4 bytes. Member e is 8 bytes, it is aligned by 8 bytes by default, the same as specified, so it is aligned to 8 bytes On the boundary, at this time, 12 bytes have been used, so 4 bytes of empty space are added, and the member e is placed from the 16th byte. At this time, the length is 24, which can already be used by 8 (member e is divisible by 8-byte alignment). In this way, a total of 24 bytes are used.
                          a b
S1 memory layout: 11**, 1111,
                          c S1.a S1.b d
S2 memory layout: 1***, 11* *,1111,****11111111

Three points are important here:
1. Each member is aligned in its own way and minimizes the length
2. The default alignment of a complex type (such as a struct) is the alignment of its longest member, so that when the member is complex When the type is used, the length can be minimized
3. The length after alignment must be an integer multiple of the largest alignment parameter in the member, so that each item can be guaranteed to be aligned when processing the array.

To add, for arrays, such as:
char a[3]; In this case, its alignment is the same as writing 3 chars respectively. That is to say, it is still aligned by 1 byte.
If you write: typedef char Array3[ 3];
The alignment of this type of Array3 is still aligned by 1 byte, not by its length.
Regardless of the type, the alignment boundary must be 1, 2, 4, 8, 16, 32, 64.. ..one of the.

Tested compiler:

GCC 2.95 3.1 3.3 3.4 4.0
MS C/C++ 7.0 7.1 8.0 beta
Borland C/C++ 5.6 6.0
Intel C/C++ 7.0 8.0 8.1
DigitalMars C/C++ 8.4
OpenWatcom 1.3
Codeplay C/C++ 2.1.7

 

(2) #pragma pack(push,1)

This is the parameter setting for the compiler, the setting of the byte alignment of the structure

Probably means to push the original alignment setting on the stack and set the new setting to 1

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326050533&siteId=291194637