どんなオブジェクトタイプT
でも、sizeof(T)
が少なくともalignof(T)
と同じくらい大きいのはいつですか?
直感的には、次のようなオブジェクトの配置を調整する場合でもそうです。
struct small {
char c;
};
通常のサイズよりも上に、「サイズ」も上方向に調整されるため、配列内のオブジェクト間の関係がアライメントを維持しながら意味を持つようになります(少なくともmy testing で。たとえば:
struct alignas(16) small16 {
char c;
};
サイズと配置の両方が16です。
少なくとも標準C++では、(長さ> 1の)配列を作成できるものであれば、これは真でなければなりません。あなたが持っている場合
_Foo arr[2];
_
およびalignof(Foo) > sizeof(Foo)
の場合、_arr[0]
_と_arr[1]
_の両方を揃えることはできません。
Zalman Sternの例 が示すように、少なくともいくつかのコンパイラーは、サイズよりも大きいアライメントで型を宣言できるため、コンパイラーは単純にその配列を宣言させませんタイプ。これは標準に準拠したC++ではありません(タイプ属性を使用します GCC拡張機能 )が、実際にはalignof(T) > sizeof(T)
を使用できることを意味します。
配列引数はsizeof(Foo) > 0
を想定しています。これは、標準でサポートされているすべての型に当てはまりますが、 o11cが示す コンパイラー拡張機能が壊れる例:一部のコンパイラーは長さ0の配列を許可します。 0 sizeof
と正のalignof
で。
#include <iostream>
typedef double foo __attribute__ ((aligned (64)));
alignas(64) double bar;
double baz __attribute__ ((aligned (64)));
int main(int argc, char *argv[]) {
std::cout << "foo sizeof: " << sizeof(foo) << " alignof: " << alignof(foo) << "\n";
std::cout << "bar sizeof: " << sizeof(bar) << " alignof: " << alignof(decltype(bar)) << "\n";
std::cout << "baz sizeof: " << sizeof(baz) << " alignof: " << alignof(decltype(baz)) << "\n";
}
コンパイル:
clang++ -std=c++11 alignof_test.cpp -o alignof_test && ./alignof_test
出力:
foo sizeof: 8 alignof: 64
bar sizeof: 8 alignof: 8
baz sizeof: 8 alignof: 8
厳密に言えば、いいえ。ただし、上記の引数re:配列は保存する必要があります。
alignof
演算子を導入した c ++ 11 standard によれば、sizeof
は次のように定義されます(5.3.3 expr.sizeofを参照)。
Sizeof演算子は、そのオペランドのオブジェクト表現のバイト数を生成します
alignof
の定義は(5.3.6 expr.alignofを参照)です。
Alignof式は、オペランドタイプのアライメント要件を生成します。
alignof
の定義は、言語の仕様ではなく、おそらくユーザーが作成した要件を指定するため、コンパイラーを操作できます。
_typedef uint32_t __attribute__ ((aligned (64))) aligned_uint32_t;
std::cout << sizeof(aligned_uint32_t) << " -> " << alignof(aligned_uint32_t);
// Output: 4 -> 64
_
編集済み
他の人が指摘しているように、そのような型は配列で使用することはできません。例えば、次のものをコンパイルしようとしています:
_aligned_uint32_t arr[2];
_
結果は_error: alignment of array elements is greater than element size
_
配列は条件に適合するために指定された型を必要とするため:sizeof(T) >= alignof(T)
多くのコンパイラーは、サイズ0
。位置合わせは、単独の要素の位置合わせと同じままです。
(とりわけ、これはビットフィールドを使用できない場合に特定のアライメントを強制するのに役立ちます)