web-dev-qa-db-ja.com

ポインタが適切に配置されたメモリ位置を指しているかどうかを確認するにはどうすればよいですか?

void *一部のストレージに対して、実装で定義された動作なしに適切にアラインされたストレージを指しているかどうかを確認する方法は?

もちろん std::align ですが、これを行うためのより効果的な方法はありますか?

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:プラットフォーム固有の(実装が定義された)ハックに依存せずに、C++標準と互換性のある方法でこれを行う必要があります。

PPS:私の母国語ではない私の英語の(理解力)をお詫び申し上げます。


EDIT(2018.08.24):タイトルから「効果的」を削除し、定義またはプラットフォームを定義したくないことを強調するために、さらに多くの文言を追加しました固有の動作。

31
jotik

アドレスを目的のアライメントで除算したときに余りがゼロでない場合、アドレスはアライメントされていません。

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

キャストのため、これはconstexprにすることはできません。

また、これは、ポインターから整数への変換でアドレスの数値表現を保持する必要があるという、実装で定義された事実に依存しています。コメントで指摘されているように、これは標準では保証されていないため、この関数は必ずしもすべてのプラットフォームに移植できるわけではありません。実装がstd::uintptr_tを提供するかどうかはオプションであるため、これも当てはまります。


これは、型に合わせて整列するときにのみ必要であると予想するので、これはより便利かもしれません:

template<class T>
bool
is_aligned(const void * ptr) noexcept {
    auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
    return !(iptr % alignof(T));
}
20
eerorika