47

Given a void * to some storage, how to check whether it points to properly aligned storage without any implementation defined behavior?

Of course we have std::align, but is there a more effective way to do this?

template <std::size_t alignment>
inline bool is_aligned(void * ptr) noexcept {
    std::size_t max = 1u;
    return std::align(alignment, 1u, ptr, max);
}

PS: I need to do this in a C++ standards-compatible fashion, without relying on any platform-specific (implementation defined) hacks.

PPS: I apologize for my (comprehension of) English, its not my native language.


EDIT (2018.08.24): Removed "effective" from the title, added even more wording to emphasize that I don't want any implementation defined or platform-specific behavior.

15
  • 2
    Also note that alignment is by definition platform specific and operating on numerical values returned from a reinterpret_cast such as suggested by @Some is inherently undefined or implementation defined behaviour. Commented Feb 7, 2017 at 15:24
  • 2
    Lastly, if you have allocated memory using new or new[] you can be certain that the memory should be well-aligned for the type you're working with. Perhaps you can enlighten us about the problem you are actually trying to solve by checking the alignment? Why do you need to check it? Commented Feb 7, 2017 at 15:27
  • 3
    @Someprogrammerdude This can be useful when one has a buffer with arbitrary raw data, and one needs to check whether parts of it can be accessed directly as some type T or whether one needs to use std::memcpy to copy the respective data from/to the buffer before/after accessing these as type T. Commented Feb 7, 2017 at 15:43
  • 3
    @Someprogrammerdude before C++17 that's only true for types with standard alignment, it's not true for something like struct OveralignedInt { alignas(1024) int i; }; Commented Feb 7, 2017 at 16:07
  • 1
    @jotik It is UB to access arbitrary raw data (char buffer) as some T even when alignment requirements are met. You'll have to begin the lifetime of the object with placement new first. Commented Feb 10, 2017 at 22:00

1 Answer 1

35

If the remainder isn't zero when dividing the address with the desired alignment, then the address isn't aligned.

inline bool
is_aligned(const void * ptr, std::uintptr_t alignment) noexcept {
    auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
    return !(iptr % alignment);
}

Ths can't be constexpr though, because of the cast.

Also, this relies on the implementation-defined fact that the conversion from pointer to integer must preserve the numeric representation of the address. As pointed out by the comments, that is not guaranteed by the standard, so this function is not necessarily portable to all platforms. That is also true, because it is optional for the implementation to provide std::uintptr_t.


I would expect this to only be needed when aligning for a type, so this might be more convenient:

template<class T>
bool
is_aligned(const void * ptr) noexcept {
    auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
    return !(iptr % alignof(T));
}
Sign up to request clarification or add additional context in comments.

18 Comments

Any pointer may be converted to an unsigned integer at least the size of uintptr_t. However, the result is implementation-defined. You're assuming a common implementation is used and the memory model is flat, basically, which is very likely these days, but not guaranteed.
@ArneVogel yeah, seems like this is not guaranteed to be strictly portable to obscure platforms, where the conversion might change the alignment.
@PhilArmstrong 2's complement is not used for unsigned numbers, it has no relevance :) But yes, any decent optimizer will be able to do that transformation.
@PhilArmstrong I tested your function, and also tested adding constexpr to my template. It works, to my surprise. I'm confused because I don't understand why reinterpret_cast can be used in a constexpr template, but not in a regular constexpr function. Can you explain / refer to the standard?
@PhilArmstrong : Constexpr function templates for which no template argument will satisfy all constexpr requirements are ill-formed, no diagnostic required. This is what both you and @user2079303 are running into.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.