Morwenn
Morwenn

Reputation: 22562

Query the alignment of a specific variable

C++11 introduced the alignas specifier to specify the alignment of a variable, and the alignof operator to query the default alignment of a type. However, I don't see any way to get the alignment of a specific variable. Let's take the following trivial example:

alignas(16) float* array;

Here is what we can do about it:

I would like a mechanism to confirm that the specific variable array is aligned on a 16 byte boundary. Is there anything in the standard to perform such a query?

Upvotes: 37

Views: 2761

Answers (3)

Columbo
Columbo

Reputation: 60999

This is currently handled by EWG 98. I submitted a paper on this:

The alignas specifier is applicable to objects, affecting their alignment requirement but not their type. It is therefore currently not possible to determine an object's actual alignment requirement. This paper proposes to permit application of alignof to objects and references.

The best you can do at this point in time is to define a separate variable holding the variable's alignment.

Upvotes: 7

manlio
manlio

Reputation: 18912

You can try with something like:

bool is_aligned(const volatile void *p, std::size_t n)
{
  return reinterpret_cast<std::uintptr_t>(p) % n == 0;
}

assert(is_aligned(array, 16));

The above assumes a flat address space and that arithmetic on uintptr_t is equivalent to arithmetic on char *.

While these conditions prevail for the majority of modern platforms, neither of which is required by the standard.

It's entirely possible for an implementation to perform any transformation when casting void * to uintptr_t as long the transformation can be reversed when casting back from uintptr_t to void * (see What is uintptr_t data type).

Further details in N4201 (it proposes, among other things, the is_aligned() operation).


EDIT

is volatile necessary here?

It allows something like:

alignas(16) volatile float a;

assert(is_aligned(&a, 16));

Without volatile you get the error

no known conversion from 'volatile float *' to 'const void *' for 1st argument

Further references:

Upvotes: 11

Elijan9
Elijan9

Reputation: 1294

You could try this:

template<size_t size, typename T>
constexpr bool IsAlignedAs(const T& v)
{
    return (reinterpret_cast<const size_t>(&v) % size) == 0;
}

std::cout << IsAlignedAs<16>(array) << std::endl;
std::cout << IsAlignedAs<32>(array) << std::endl;

Upvotes: 3

Related Questions