2016-03-25 3 views
33

C++ 11では、変数の配置を指定するためにalignas specifierが導入され、型のデフォルトの配置を照会するためにalignof operatorが導入されました。しかし、私は特定の変数のアライメントを得る方法はありません。のは、以下の簡単な例を見てみましょう:ここ特定の変数の配置の照会

alignas(16) float* array; 

は、我々はそれについて何ができるかです:私たちは何をしたい明らかではありません

  • alignof(float*)戻り8、。
  • alignof(array)は正確に私たちが望むものですが、これはコンパイラ拡張です。標準で指定されたalignofは、特定の変数で使用することはできません。
  • alignof(decltype(array))は8を返します。これはかなり期待されていましたが、私たちが望むものではありませんでした。
  • std::alignment_ofalignofで実装されているため、あまり役に立ちません。

特定の変数arrayが16バイトの境界に位置合わせされていることを確認するメカニズムが必要です。このようなクエリを実行するための標準はありますか?

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)); 

は、上記のフラットなアドレス空間を想定し、uintptr_t上の算術char *上の算術と同等です:

+0

* alignof *はそれを提供する必要はありません - コンパイル時に最低限の契約を返します* - 実行時に値*を必要とする*。特定の変数は、ページ境界*、メガバイト境界、または実行時の何らかのもの(つまり、約束されているか要求されているよりも「良い」)に非常によく揃えられます。変数のアドレスを取得し、必要なアライメント値で均等に割り切れることを確認します。 – tofro

+0

@tofro右、それを指定するのを忘れていましたが、変数名に使用されたときにランタイムになるために半分の期待された 'alignof'がありました(私はこれがコンパイラの拡張機能です)。コンパイル時にすべてがわかるとは思っていませんでした。 – Morwenn

+0

*#ALIGNED8(x)((&(x)&& 0x7)== 0)*があなたの目的に合致しないのか、標準がこの単純な構造を複製するものでなければならないのか、 – tofro

答えて

8

あなたのような何かを試すことができます。

これらの条件は、現代のプラットフォームの大部分に優先しますが、どちらも標準では要求されていません。

それは(What is uintptr_t data type参照)限りuintptr_tからvoid *に戻ってキャストするとき変換は逆にすることができるuintptr_tからvoid *を鋳造する際に、任意の変換を実行するための実装のために完全に可能です。

詳細はN4201(特に、is_aligned()操作を提案しています)。 EDIT


はここでは必要volatileのですか?

それは何かのようにできます:あなたがエラーを取得する

alignas(16) volatile float a; 

assert(is_aligned(&a, 16)); 

volatileなし

第一引数

のための 'CONSTのvoid *' から '揮発性のフロート*' から知られていない変換

さらなる参照:

+0

なぜ標準化された関数がそれらの保証を必要とするなら有用であるのか分かります。 N4201 [拒否されました](https://issues.isocpp.org/show_bug.cgi?id=61)。 – Morwenn

+0

@manlioは、ここでは 'volatile'が必要ですか?もしそうなら、それは 'const void * volatile'であってはなりませんか? – user5434231

+0

@ user5434231答えにいくつかの参照を追加しました – manlio

2

あなたはこの試みることができる:これは、現在EWG 98によって処理され

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; 
+0

ちなみに、 'static_assert(IsAlignedAs(配列)、" 16に整列されていない配列 ");'あなたの配列はstatic_assert(IsAlignedAs <32>(配列))は使用できません。 ");'これが本当であるかどうかにかかわらず、コンパイル時に未定です。 – Elijan9

+0

clangの定数式ではありません。 – Jarod42

+0

確かにgcc固有のようです。コンパイル時のアドレスの整列をチェックして(最終的な位置にリンクする前に)、少し早過ぎました... – Elijan9

4

を。私はこの上a paperを提出:

alignas指定子が自分のタイプを彼らのアライメント要件に影響を与えることはなく、オブジェクトに適用されます。したがって、現時点では、オブジェクトの実際のアラインメント要件を決定することは現在不可能です。本稿では、オブジェクトと参照にalignofの適用を許可することを提案する。

この時点でできることは、変数の配置を保持する別の変数を定義することです。

+1

他の人がそれについて考えて、作業を開始していることを嬉しく思っています:) – Morwenn

関連する問題