In some situations where fine-grained control over memory is required, we must be careful about how we pack bytes into memory. These alignment issues can arise e.g. with particular kinds of processors or when crafting low-level input/output for hardware.
C++11 offers the alignof
/alignas
operators (OpenSTD) but unfortunately they are not implemented in the Visual Studio 2013 compiler (VS2013). It is possible to lean on std::align
, however (CPP Align).
Suppose we have a 32 byte region of memory, and we need to always align our entries along 8-byte boundaries. In the example, we use up the first 9 bytes of the memory:
#define MEM_SIZE 32
#define HEADER "\x01\x02\x03\x04\x05\x06\x07\x08\x09"
#define HEADER_LENGTH 9
char data[MEM_SIZE] = { 0 };
memcpy(data, HEADER, HEADER_LENGTH);
Our data buffer looks like this:
The next region of data needs to be aligned at an 8 byte boundary (i.e. at the 16th byte), and we can lean on std::align
:
#define ALIGNMENT 8
#define BUFFER "\x10\x11\x12\x13\x14\x15\x16\x17"
#define BUFFER_LENGTH 8
void *endOfHeader = &(data[0]) + HEADER_LENGTH;
std::size_t space = MEM_SIZE - HEADER_LENGTH;
void *nextAvailableByte = std::align(ALIGNMENT, BUFFER_LENGTH, endOfHeader, space);
memcpy(nextAvailableByte, BUFFER, BUFFER_LENGTH);
std::align
takes four arguments:
- The size of the alignment (in our case, 8 bytes)
- length of the data you’d like to write (in our case, also 8 bytes)
- The (possibly mis-aligned) pointer to the next valid address to write buffer to
- How much space is left in
data
. Ifstd::align
cannot find a spot to insert intodata
, it will return a null pointer (i.e. there was not enough space left, asBUFFER_LENGTH
was too large). The result of ourmemcpy
isBUFFER
copied nicely along our 8 byte boundary:
A complete example is available on github.