About Data Alignment (Windows CE 5.0)
Alignment is a property of a memory address, expressed as the numeric address modulo a power of 2. For example, the address 0x0001103F modulo 4 is 3; that address is said to be aligned to 4n+3, where 4 indicates the chosen power of 2. The alignment of an address depends on the chosen power of two. The same address modulo 8 is 7.
An address is said to be aligned to X if its alignment is Xn+0.
CPUs execute instructions that operate on data stored in memory, and the data are identified by their addresses in memory. In addition to its address, a single datum also has a size. A datum is called naturally aligned if its address is aligned to its size, and misaligned otherwise. For example, an 8-byte floating-point datum is naturally aligned if the address used to identify it is aligned to 8.
Reading data that is not naturally aligned requires much more hardware complexity. Many CPUs, such as those based on Alpha, IA-64, MIPS, and SuperH architectures, refuse to read misaligned data. When a program requests that one of these CPUs access data that is not aligned, the CPU enters an exception state and notifies the software that it cannot continue.
The behavior of Windows operating systems with regard to accessing misaligned data varies based on the target architecture and version of the software. On the Windows CE platforms ARM, MIPS, and SH, the operating system default is to give the application an exception notification when a misaligned access is requested. For IA-64, Windows NT supports the SetErrorMode API to enable automatic handling of misaligned accesses, but Windows CE does not provide this API. The purpose of this change in behavior for newer operating system versions is to strongly discourage reliance on misaligned memory accesses, which can incur enormous performance losses on targets that do not support them in hardware.
Compiler handling of data alignment
The compiler attempts to allocate data in a way that prevents data misalignment.
For simple data types, the compiler assigns addresses that are multiples of the size in bytes of the data type. Thus, the compiler assigns addresses to variables of type long that are multiples of four, setting the bottom two bits of the address to zero.
In addition, the compiler pads structures in a way that naturally aligns each element of the structure. Consider the structure struct x_ in the following code example:
struct x_
{
char a; // 1 byte
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
} MyStruct;
The compiler pads this structure to enforce alignment naturally.
The following code example shows how the compiler places the padded structure in memory:
// Shows the actual memory layout
struct x_
{
char a; // 1 byte
char _pad0[3]; // padding to put 'b' on 4-byte boundary
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
char _pad1[1]; // padding to make sizeof(x_) multiple of 4
}
Both declarations return sizeof(struct x_) as 12 bytes.
The second declaration includes two padding elements:
- char _pad0[3] to align the int b member on a four-byte boundary
- char _pad1[1] to align the array elements of the structure struct _x bar[3];
The padding aligns the elements of bar[3] in a way that allows natural access. The following code example shows the bar[3] array layout:
adr
offset element
------ -------
0x0000 char a; // bar[0]
0x0001 char pad0[3];
0x0004 int b;
0x0008 short c;
0x000a char d;
0x000b char _pad1[1];
0x000c char a; // bar[1]
0x000d char _pad0[3];
0x0010 int b;
0x0014 short c;
0x0016 char d;
0x0017 char _pad1[1];
0x0018 char a; // bar[2]
0x0019 char _pad0[3];
0x001c int b;
0x0020 short c;
0x0022 char d;
0x0023 char _pad1[1];
See Also
Working with Packing Structures | __unaligned Keyword
Send Feedback on this topic to the authors