#pragma pack, _ _packed

The #pragma pack directive modifies the current alignment rule for members of structures following the directive.

The #pragma pack directive modifies the current alignment rule for only the members of structures whose declarations follow the directive. 

It does not affect the alignment of the structure directly, but by affecting the alignment of the members of the structure,
it may affect the alignment of the overall structure according to the alignment rule.

The #pragma pack directive cannot increase the alignment of a member, but rather can decrease the alignment.
For example, for a member with data type of integer (int), a #pragma pack(2) directive would cause that member to be packed
in the structure on a 2-byte boundary, while a #pragma pack(4) directive would have no effect.

The #pragma pack directive is stack based. All pack values are pushed onto a stack as the source code is parsed. The value at the top of the current pragma pack stack is the value used to pack members of all subsequent structures within the scope of the current alignment rule.

#pragma pack stack is associated with the current element in the alignment rule stack.
Alignment rules are specified with the -qalign compiler option or with the #pragma options align directive.
If a new alignment rule is created, a new #pragma pack stack is created.
If the current alignment rule is popped off the alignment rule stack, the current #pragma pack stack is emptied and
the previous #pragma pack stack is restored. Stack operations (pushing and popping pack settings) affect only the current #pragma pack stack.

The #pragma pack directive causes bitfields to cross bitfield container boundaries.

Examples

  1. In the code shown below, the structure S2 will have its members packed to 1-byte, but structure S1 will not be affected. This is because the declaration for S1 began before the pragma directive. However, since the declaration for S2 began after the pragma directive, it is affected.

    struct s_t1 {
        char a;    
        int b;
        #pragma pack(1)
        struct s_t2 {    
                char x;
                int y;
        } S2;
        char c;
        int b;
    } S1;
  2. This example shows how a #pragma pack directive can affect the size and mapping of a structure:
    struct s_t {
        char a;
        int b;
        short c;
        int d;
    }S;
     
    Default mapping:With #pragma pack(1):
    sizeof S = 16 sizeof S = 11
    offsetof a = 0 offsetof a = 0
    offsetof b = 4 offsetof b = 1
    offsetof c = 8 offsetof c = 5
    offsetof d = 12 offsetof d = 7
    align of a = 1 align of a = 1
    align of b = 4 align of b = 1
    align of c = 2 align of c = 1
    align of d = 4 align of d = 1
#pragma pack(n)
#pragma pack()
#pragma pack({push|pop}[,name] [,n])
 
#pragma pack(n)
#pragma pack()
#pragma pack({push|pop}[,name] [,n])
Parameters
 
 
n
Sets an optional structure alignment; one of: 1, 2, 4, 8, or 16
Empty list
Restores the structure alignment to default
push
Sets a temporary structure alignment
pop
Restores the structure alignment from a temporarily pushed alignment
name
An optional pushed or popped alignment label
 

Description

Use this pragma directive to specify the maximum alignment of struct and union members.

The #pragma pack directive affects declarations of structures following the pragma directive to the next #pragma pack
or the end of the compilation unit.

Note:

This can result in significantly larger and slower code when accessing members of the structure.
Use either __packed or #pragma pack to relax the alignment restrictions for a type and the objects defined using that type.
Mixing __packed and #pragma pack might lead to unexpected behavior.

Description
Use the __packed keyword to decrease the data type alignment to 1.
__packed can be used for two purposes:

When used with a struct or union type definition, the maximum alignment of members of that struct or union is set to 1,
to eliminate any gaps between the members. The type of each members also receives the __packed type attribute.

When used with any other type, the resulting type is the same as the type without the __packed type attribute,
but with an alignment of 1. Types that already have an alignment of 1 are not affected by the __packed type attribute.

A normal pointer can be implicitly converted to a pointer to __packed, but the reverse conversion requires a cast.

Note:
Accessing data types at other alignments than their natural alignment can result in code that is significantly larger and slower.
Use either __packed or #pragma pack to relax the alignment restrictions for a type and the objects defined using that type.
Mixing __packed and #pragma pack might lead to unexpected behavior.

Example

__packed struct X
{
  char ch;
  int i;
};
/* No pad bytes */

void Foo( struct X * xp ) /* No need for __packed here */
{
  int * p1 = &xp->i;/* Error:"int *">"int __packed *" */
  int __packed * p2 = &xp->i; /* OK */
  char * p2 = &xp->ch; /* OK, char not affected */
}
 

原文地址:https://www.cnblogs.com/shangdawei/p/3118751.html