EAAlignment provides a number of utilities for working with variable alignment. These include:
Entity Description EAAlignOf(type) Macro which returns the alignment of the given type as a constant expression. AlignOf<T> Template which returns the alignment of the given type. AlignAddressUp
AlignAddressDownFunction which aligns an arbitrary address up or down to the next user-supplied power of two. AlignObjectUp
AlignObjectDownFunction which aligns an arbitrary object up or down to the next user-supplied power of two. GetAlignment
IsAddressAligned
IsObjectAligned<T>
IsAligned<T>Gets information about alignment. AlignedType Template which portably allows the re-typing of a class to have a specific alignment. AlignedArray Template which implements an array of an arbitrary class with a given alignment. AlignedObject Template which implements an instance of an arbitrary class with a given alignment. ReadMisalignedUint16
ReadMisalignedUint32
ReadMisalignedUint64Function which safely and portably reads potentially misaligned memory. WriteMisalignedUint16
WriteMisalignedUint32
WriteMisalignedUint64Function which safely and portably writes potentially misaligned memory.
We'll discuss some of these briefly.
EAAlignOf is your basic macro for retrieving the alignment of an object by its type. Recent versions of EABase define EA_ALIGN_OF, so EAAlignOf is currently a duplication of the EABase functionality.
Example usage:
printf("Alignment of type 'int' is %u.\n", (unsigned)EAAlignOf(int));
This class makes an aligned typedef for a given class based on a user-supplied class and alignment. This class exists because of a weakness in VC++ whereby it can only accept __declspec(align) and thus EA_PREFIX_ALIGN usage via an integer literal (e.g. "16") and not an otherwise equivalent constant integral expression (e.g. sizeof Foo).
Example usage:
const size_t kAlignment = 32; // Note that in this case the alignment is defined elsewhere as a non-literal.
AlignedType<Widget, kAlignment>::Type widgetAlign128;
widgetAlign128.DoSomething();
ReadMisaligned reads an unsigned integer from a possibly non-aligned address. The MIPS processor on the PS2, for example, cannot read a 32-bit value from an unaligned address. This function can be used to make reading such misaligned data portable..
Example usage:
void DoSomeReading(const char* pData)
{
uint16_t x = ReadMisalignedUint16(pData);
pData += sizeof(uint16_t);
uint32_t y = ReadMisalignedUint32(pData);
pData += sizeof(uint32_t);
uint64_t z = ReadMisalignedUint64(pData);
pData += sizeof(uint64_t);
...
}