4.5.2. The __packed qualifier and unaligned accesses to data
The __packed qualifier sets the alignment of any valid type to one. This enables objects of packed type to be read or written using unaligned accesses.
Examples of objects that can be packed include:
structures
unions
pointers.
See __packed in the Compiler Reference Guide for more information on the __packed qualifier.
Unaligned fields in structures
For efficiency, fields in a structure are located on their natural size boundary. This means that the compiler often inserts padding between fields to ensure they are aligned.
When space is at a premium, the __packed qualifier can be used to create structures without padding between fields. Structures can be packed in two ways:
The entire struct can be declared as __packed. For example:
__packed struct mystruct
{
char c;
short s;
} // not recommended
Each field of the structure inherits the __packed qualifier.
Declaring an entire struct as __packed typically incurs a penalty both in code size and performance. See __packed structures versus individually __packed fields for more information.
Individual non-aligned fields within the struct can be declared as __packed. For example:
struct mystruct
{
char c;
__packed short s; // recommended
}
This is the recommended approach to packing structures. See __packed structures versus individually __packed fields for more information.
Note
The same principles apply to unions. You can declare either an entire union as __packed, or use the __packed attribute to identify components of the union that are unaligned in memory.
Reading from and writing to structures qualified with __packed requires unaligned accesses and can therefore incur a performance penalty. See __packed structures versus individually __packed fields for more information.
By default, the ARM compiler expects conventional C pointers to point to an aligned word in memory, as this enables the compiler to generate more efficient code.
If you wish to define a pointer that can point to a word at any address, then you must specify this using the __packed qualifier when defining the pointer. For example:
__packed int *pi; // pointer to unaligned int
When a pointer is declared as __packed, the ARM compiler generates code that correctly accesses the dereferenced value of the pointer, regardless of its alignment. The generated code consists of a sequence of byte accesses, or variable alignment-dependent shifting and masking instructions, rather than a simple LDR instruction. Consequently, declaring a pointer as __packed incurs a performance and code size penalty.
Unaligned LDR instructions for accessing halfwords
In some circumstances the compiler might intentionally generate unaligned LDR instructions. In particular, the compiler can do this to load halfwords from memory, even where the architecture supports dedicated halfword load instructions.
For example, to access an unaligned short within a __packed structure, the compiler might load the required halfword into the top half of a register and then shift it down to the bottom half. This operation requires only one memory access, whereas performing the same operation using LDRB instructions requires two memory accesses, plus instructions to merge the two bytes.