You copied the Doc URL to your clipboard.

Packing data structures

You can reduce the amount of memory that your application requires by packing data into structures. This is especially important if you need to store and access large arrays of data in embedded systems.

If individual data members in a structure are not packed, the compiler can add padding within the structure for faster access to individual members, based on the natural alignment of each member. Arm® Compiler provides a pragma and attribute to pack the members in a structure or union without any padding.

Table 3-12 Packing members in a structure or union

Pragma or attribute Description
#pragma pack (n) For each member, if n bytes is less than the natural alignment of the member, then set the alignment to n bytes, otherwise the alignment is the natural alignment of the member. For more information see #pragma pack (n) and __alignof__.
__attribute__((packed)) This is equivalent to #pragma pack (1). However, the attribute can also be used on individual members in a structure or union.

Packing the entire structure

To pack the entire structure or union, use __attribute__((packed)) or #pragma pack(n) to the declaration of the structure as shown in the code examples. The attribute and pragma apply to all the members of the structure or union. If the member is a structure, then the structure has an alignment of 1-byte, but the members of that structure continue to have their natural alignment.

When using #pragma pack(n), the alignment of the structure is the alignment of the largest member after applying #pragma pack(n) to the structure.

Each example declares two objects c and d. Copy each example into file.c and compile:

armclang --target=arm-arm-none-eabi -march=armv8-a -c file.c -o file.o

For each example use linker option --info=sizes to examine the memory used in file.o.

armlink file.o --info=sizes

The linker output shows the total memory used by the two objects c and d. For example:

Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
  36          0          0          0         24          0   str.o
---------------------------------------------------------------------------
  36          0         16          0         24          0   Object Totals

Table 3-13 Packing structures

Code Packing Size of structure
struct stc
{
    char one;
    short two;
    char three;
    int four;
} c,d;


int main (void)
{
    c.one=1;
    return 0;
}

Figure 3-1 Structure without packing attribute or pragma


12. The alignment of the structure is the natural alignment of the largest member. In this example, the largest member is an int.
struct __attribute__((packed)) stc
{
    char one;
    short two;
    char three;
    int four;
} c,d;


int main (void)
{
    c.one=1;
    return 0;
}

Figure 3-2 Structure with attribute packed


8. The alignment of the structure is 1 byte.
#pragma pack (1)
struct stc
{
    char one;
    short two;
    char three;
    int four;
} c,d;


int main (void)
{
    c.one=1;
    return 0;
}

Figure 3-3 Structure with pragma pack with 1 byte alignment


8. The alignment of the structure is 1 byte.
#pragma pack (2)
struct stc
{
    char one;
    short two;
    char three;
    int four;
} c,d;


int main (void)
{
    c.one=1;
    return 0;
}

Figure 3-4 Structure with pragma pack with 2 byte alignment


10. The alignment of the structure is 2 bytes.
#pragma pack (4)
struct stc
{
    char one;
    short two;
    char three;
    int four;
} c,d;


int main (void)
{
    c.one=1;
    return 0;
}

Figure 3-5 Structure with pragma pack with 4 byte alignment


12. The alignment of the structure is 4 bytes.

Packing individual members in a structure

To pack individual members of a structure, use __attribute__((packed)) on the member. This aligns the member to a byte boundary and therefore reduces the amount of memory required by the structure as a whole. It does not affect the alignment of the other members. Therefore the alignment of the whole structure is equal to the alignment of the largest member without the __attribute__((packed)).

Table 3-14 Packing individual members

Code Packing Size
struct stc
{
    char one;
    short two;
    char three;
    int  __attribute__((packed)) four;
} c,d;


int main (void)
{
    c.one=1;
    return 0;
}

Figure 3-6 Structure with attribute packed on individual member


10. The alignment of the structure is 2 bytes because the largest member without __attribute__((packed)) is short.

Accessing packed members from a structure

If a member of a structure or union is packed and therefore does not have its natural alignment, then to access this member, you must use the structure or union that contains this member. You must not take the address of such a packed member to use as a pointer, because the pointer might be unaligned. Dereferencing such a pointer can be unsafe even when unaligned accesses are supported by the target, because certain instructions always require word-aligned addresses.

Note

If you take the address of a packed member, in most cases, the compiler generates a warning.
struct __attribute__((packed)) foobar 
{
  char x;
  short y;
}; 

short get_y(struct foobar *s) 
{
    // Correct usage: the compiler will not use unaligned accesses
    // unless they are allowed.
    return s->y;
} 

short get2_y(struct foobar *s) 
{
    short *p = &s->y; // Incorrect usage: 'p' might be an unaligned pointer.
    return *p;  // This might cause an unaligned access.
}
Was this page helpful? Yes No