3.1.4. 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.

Note

__packed is not, strictly speaking, a type qualifier. It is included in this section because it behaves like a type qualifier in most respects.

__packed

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.

Note

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
}

volatile

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.

Copyright © 1997, 1998 ARM Limited. All rights reserved.ARM DUI 0041C