Aligning arrays

When developing stack-based containers for RDESTL I’ve encountered the following problem - how to get block of uninitialized memory that’s aligned properly for type T. Consider fixed_vector class:

template
class fixed_array
{
    ...
    char    m_data[N * sizeof(T)];
Size is OK (we need N elements of type T), sadly alignment is invalid here. It may not be a problem for majority of cases, but try storing _m128s… Even when using 32-bit variables, they should be aligned on natural boundary (4 bytess) in order to rely on writes/reads being atomic. Our first task – find out alignment of type T. In order to determine it, we create helper class with element of type T stored just after char, then get its offset:
template
struct alignof_helper
{
    char    x;
    T       y;
};
template
struct alignof
{
    enum
    {
        res = offsetof(alignof_helper, y)
    };
};
Just to make sure it works (you may need to disable warning C4324 (structure was padded due to __declspec(align)) :
CHECK_EQUAL(16, rde::alignof<__m128>::res);

First part of a problem solved. However, “res” cannot be simply used as an argument to __declspec(align). Instead, we have to create basic types with most common alignments.

__declspec(align(16)) struct aligned16 { uint64_t member[2]; };
template struct type_with_alignment
{
    typedef char err_invalid_alignment[N > 0 ? -1 : 1];
};
template<> struct type_with_alignment<0> {};
template<> struct type_with_alignment<1> { uint8_t member; };
template<> struct type_with_alignment<2> { uint16_t member; };
template<> struct type_with_alignment<4> { uint32_t member; };
template<> struct type_with_alignment<8> { uint64_t member; };
template<> struct type_with_alignment<16> { aligned16 member; };

...

template
struct aligned_as
{
    typedef typename internal::type_with_alignment<alignof::res> res;
};
If necessary, some more types should be provided.

Finally, we create array of properly aligned types instead of chars. We also have to modify array size, as element size is no longer one byte, it needs to be corrected:

typedef typename aligned_as::res    etype_t;
etype_t                    m_data[(N * sizeof(T)) / sizeof(etype_t)];
.

Old comments

Reg 2009-03-08 11:26:37

I suppose you could use __alignof instead of this alignof_helper struct with offsetof.

admin 2009-03-08 11:59:45

Sadly, __alignof isn’t really reliable: http://www.nabble.com/-Format--Asserts-with-non-default-structure-packing-in-1.37-(MSVC)-td21215959.html

jason gregory 2010-04-04 23:40:33

[…] has said … ZEPPELIN drummer John Bonham's son Jason behind the. kit. Since the acclaimed show, …Aligning arrays | .mischief.mayhem.soap.When developing stack-based containers for RDESTL I've encountered the following problem - how to […]

More Reading