| |||
| Home > ARM Compiler Reference > Compiler-specific features > Type qualifiers | |||
This section describes the implementation of various standard C, C++, and ARM-specific type qualifiers. These type qualifiers can be used to instruct the compiler to treat the qualified type in a special way. Standard qualifiers that do not have ARM-specific behavior or restrictions are not documented.
__packed is not, strictly speaking, a type
qualifier. It is included in this section because it behaves like
a type qualifier in most respects.
The __packed qualifier sets the alignment
of any valid type to 1. This means:
there is no padding inserted to align the packed object
objects of packed type are read or written using unaligned accesses.
The __packed qualifier cannot be used on:
floating-point types
structures or unions with floating-point fields.
The __packed qualifier does not affect
local variables of integral type.
The top level alignment specified with the -zat compiler
option is applied to global objects. This means that there can be
padding between two packed globals. The structure alignment specified
with the -zas compiler option does not apply to
packed structures.
Packed types must be specified with __packed.
If you want to use packed rather than __packed,
you must define it:
#define packed __packed
The __packed qualifier applies to all members
of a structure or union when it is declared using __packed.
There is no padding between members, or at the end of the structure. All
sub-structures of a packed structure must be declared using __packed.
A packed structure or union is not assignment compatible with the corresponding unpacked structure. Because the structures have a different memory layout, the only way to assign a packed structure to an unpacked structure is by a field by field copy.
The effect of casting away __packed is
undefined. The effect of casting a non-packed structure to __packed is
undefined. It is legal to implicitly cast a pointer to an integral type
to a pointer to a packed integral type.
There are no packed array types. A packed array is simply an array of objects of packed type. There is no padding.
On ARM processors, access to unaligned data can be expensive, taking up to seven instructions and three work registers. Data accesses through packed structures should be minimized to avoid increase in code size, or performance loss.
The __packed qualifier is useful to map
a structure to an external data structure, or for accessing unaligned
data, but it is generally not useful to save data size because of
the relatively high cost of access.
See Example 3.1.
Example 3.1.
typedef __packed struct
{
char x; // all fields inherit the __packed qualifier
int y;
}X; // 5 byte structure, natural alignment = 1
int f(X *p)
{
return p->y; // does an unaligned read
}
typedef struct
{
short x;
char y;
__packed int z;
char a;
}Y; // 8 byte structure, natural alignment = 2
int g(Y *p)
{
return p->z + p->x; // only unaligned read for z
}
The standard qualifier volatile informs the compiler that the qualified type contains data that may be changed from outside the program. The compiler will not attempt to optimize accesses to volatile qualified types. For example, volatile structures can be mapped onto memory-mapped hardware.
In ARM C and C++, a volatile qualified object is accessed if any word or byte (or halfword on ARM architecture that have halfword support) of the object is read or written. For volatile qualified objects, reads and writes occur as directly implied by the source code, in the order implied by the source code. The effect of accessing a volatile short is undefined for ARM architectures that do not have halfword support.