GCC has recently implemented alignment support. In this post I will discuss what this is and how you can use it.

There are four additions that are related to alignment support, these are the alignas alignment-specifier, the alignof expression, alignment arithmetic library support and std::align for aligning pointers. I will explain these all individually below.

Alignment is the requirement that the memory address of the first byte of certain types of objects be modulo zero with respect to some integer. For example, int32_t has an alignment of 4, it can only be placed in memory locations divisible by 4.

Alignments are ordered from weaker to stronger or stricter. An alignment that is stricter than another has a larger value. It is said to be stricter because there are less memory locations at which it can be placed, therefore the compiler is stricter in where that object can be placed.

Alignof

An alignof expression is used to get the alignment of a type, or a reference to a complete object. For example, if you have a variable declared int32_t x; , then alignof(x) is 4.

If you ask for the alignment of an array type, the value is the alignment of the elements of the array.

Alignas

The alignas keyword allows you to specify that a variable or data member of a class has a stricter alignment than that which it inherently has. An alignas declaration is placed before a variable. For example, to declare that the variable x has the same alignment as int64_t , you would write:

alignas(int64_t) int32_t x;

The value provided can be either a number or a type, when it is a type type-id it is the same as writing alignas(alignof(type-id)) .

The alignment specified cannot be less strict than the alignment that would normally be required for that entity.

Library alignment arithmetic

The library provides a class template called aligned_storage , its declaration is as follows:

template <std::size_t Len, std::size_t Alignment> struct aligned_storage;

It provides a member typedef type which is a POD type suitable for use as storage for any object whose length is no greater than Len and whose alignment is a divisor of Alignment . For example, to declare some memory that can store anything aligned up to 8 and no longer than 20, you would write the following:

typedef std::aligned_storage<20, 8>::type MyAligned; MyAligned x;

This addition allows the variant class that I wrote previously to be implemented a little more cleanly. The member variable m_storage can now be declared as follows:

typedef typename std::aligned_storage< max<Sizeof, First, Types...>::value, max<Alignof, First, Types...>::value >::type AlignedStorage; AlignedStorage m_storage;

Aligning pointers at runtime

The library also provides a function std::align , that computes a pointer with the alignment requested. Its declaration is

void* align(std::size_t alignment, std::size_t size, void *&ptr, std::size_t space) noexcept;

The idea is that you have some memory starting at ptr , of at least length space , and you want the first possible address inside that space that has length size and aligned to alignment . If ptr is not at the required alignment, it will be moved along as long as there is space to do so.

Suppose that you have a ptr to memory address 0xF (I know that’s not valid memory but it’s easiest for the example), you have 20 bytes remaining in that space, you want an alignment of 4 and length 8, you would call:

size_t space = 20; auto result = align(4, 8, ptr, space);

and ptr would be incremented to 0x10 , and space would be changed to 19, it would also return the value 0x10 .

If there is no valid memory for the request, then nullptr is returned. This would happen if moving to the right alignment doesn’t leave enough space.