Packed structs
This version of the compiler adds packed structs, as available in ARM's
later compilers.
A packed struct is one in which there is neither padding between fields to
ensure the natural alignment of each field, nor trailing padding to ensure
the natural alignment of a following struct within an array.
Many applications read data from and write data to networks and computer
buses in formats defined by international standards and by other programs
executing on different processors. The data format is fixed. Data read and
data to be written can be precisely mapped in C using packed structs.
However, packed structs cannot support reading values of the wrong
endianness.
On the ARM, access to unaligned data can be expensive (taking up to 7
instructions and 2 extra work registers). Data accesses via packed structs
should be minimised to avoid performance loss. Generally, internal data
structures should not be packed.
There is no command-line option to change the default packing of structures.
Packed structures must be specified with a new type qualifier: __packed.
__packed behaves as a type qualifier (like volatile) and may qualify any non
floating point type. Floating types may not be fields of packed structures.
A packed struct or union type must be declared explicitly. It is a different
type from the corresponding non packed type and its packedness is an
attribute of its struct tag (so __packed is more than just a type qualifier).
Any variables declared using a packed tag automatically inherit the packed
attribute, so __packed does not have to be specified:
__packed struct P { ... };
struct P pp; /* pp is a packed struct */
In consequence, the following will be faulted:
struct Foo { ... };
__packed struct Foo PackedFoo; /* illegal */
or
struct Foo { ... };
typedef __packed struct Foo PackedFoo; /* illegal */
This ensures that a packed struct can never be assignment compatible with an
unpacked struct. This could happen if __packed were merely a type qualifier
like volatile and const.
Each field of a packed struct or packed union inherits the packed qualifier.
There are no packed array types. A packed array is simply an array of objects
of packed type (there is no inter-element padding).
The effect of casting away __packed is undefined. For example:
int f(__packed int *px)
{
return *(int *)px; /* undefined behaviour */
}
A struct (or union) sub-field of a packed struct or union must be declared
to have packed struct (or packed union) type.
struct S {...};
__packed struct P {...};
struct T {
struct S ss; /* OK */
struct P pp; /* OK */
};
__packed struct Q {
struct S ss; /* faulted - sub-structs must be packed */
struct P pp; /* OK */
};
The substructs are abutted without any intermediate padding, and they contain
no internal padding themselves (because they must be packed).
__packed struct P { char c; int x; };
__packed struct {
struct P X;
char z;
struct P Y;
} Q;
<-------------------- Q -------------------->
<-------- X --------> <-------- Y -------->
+---+---+---+---+---+---+---+---+---+---+---+
byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|
| c | ------x------ | z | c | ------x------ |
+---+---+---+---+---+---+---+---+---+---+---+
|