構造体メンバーの配置がわかっている場合、構造タイプの配置を見つけることができますか?
例えば。にとって:
struct S
{
a_t a;
b_t b;
c_t c[];
};
S = max(alignment_of(a)、alignment_of(b)、alignment_of(c))のアライメントですか?
インターネットを検索すると、「構造化タイプの場合、その要素のいずれかの最大のアライメント要件が構造のアライメントを決定する」(すべてのプログラマーがメモリについて知っておくべきこと)がわかりましたが、標準(最新)ではリモートで類似したものは見つかりませんでしたより正確にドラフト)。
編集: すべての回答に感謝します。特に、元の質問に本当に良い回答を提供してくれたRobertGambleと他の人に感謝します。
要するに:
構造体部材の位置合わせ要件を確実にするには、構造体の位置合わせは、少なくともその最も厳密な部材の位置合わせと同じくらい厳密でなければなりません。
構造の配置を決定することに関して、いくつかのオプションが提示されました、そして少しの研究でこれは私が見つけたものです:
- c ++ std :: tr1 :: alignment_of
- まだ標準ではありませんが、近い(テクニカルレポート1)、C++0xにあるはずです
- 最新のドラフトには、次の制限があります。前提条件:Tは、完全型、参照型、または未知の境界の配列である必要がありますが、関数型または(場合によってはcv修飾された)voidであってはなりません。
- これは、C99フレキシブルアレイで提示したユースケースが機能しないことを意味します(フレキシブルアレイは標準のc ++ではないため、これはそれほど驚くべきことではありません)
- 最新のc++ドラフトでは、新しいキーワードで定義されています-alignas(これには同じ完全な型の要件があります)
- 私の意見では、c ++標準がC99フレキシブル配列をサポートする場合、要件を緩和することができます(構造とフレキシブル配列の配置は、配列要素の数に基づいて変更されるべきではありません)
- c ++ boost :: alignment_of
- 主にtr1の代替品
- voidに特化しているようで、その場合は0を返します(これはc ++ドラフトでは禁止されています)
- 開発者からの注意:厳密に言えば、ALIGNOF(T)の値はTの真のアラインメントの倍数であることにのみ依存する必要がありますが、実際には、私たちが知っているすべての場合に正しい値を計算します。
- これが柔軟な配列で機能するかどうかはわかりません(一般的には機能しない可能性があります。これは私のプラットフォームに固有のコンパイラに解決されるため、一般的な場合の動作はわかりません)
- Andrew Topは、回答の配置を計算するための簡単なテンプレートソリューションを提示しました
- これはブーストが行っていることに非常に近いようです(私が見る限り、ブーストは計算された配置よりも小さい場合、オブジェクトサイズを配置として追加で返します)、おそらく同じ通知が適用されます
- これは柔軟なアレイで機能します
- Windbg.exeを使用して、シンボルの配置を確認します
- コンパイル時ではなく、コンパイラ固有で、テストしませんでした
- タイプを含む匿名構造でoffsetofを使用する
- 答えを見る、信頼できない、c++非PODとの移植性がない
- コンパイラ組み込み関数、例えば。MSVC __alignof
- 柔軟なアレイで動作します
- alignofキーワードは最新のC++ドラフトにあります
「標準」ソリューションを使用する場合は、std :: tr1 :: alignment_ofに制限されますが、c++コードをc99の柔軟な配列と混合すると機能しません。
私が見ているように、解決策は1つだけです-古い構造体ハックを使用してください:
struct S
{
a_t a;
b_t b;
c_t c[1]; // "has" more than 1 member, strictly speaking this is undefined behavior in both c and c++ when used this way
};
この場合(および他のすべての場合)、cおよびc++標準の相違とそれらの違いの増大は残念なことです。
もう1つの興味深い質問は、(移植可能な方法で構造の位置合わせを見つけることができない場合)可能な限り最も厳しい位置合わせ要件は何かということです。私が見つけることができるいくつかの解決策があります:
- boost(内部)はさまざまなタイプのユニオンを使用し、その上でboost::alignment_ofを使用します
- 最新のc++ドラフトにはstd::aligned_storageが含まれています
- default-alignmentの値は、サイズがLen以下のC++オブジェクトタイプの最も厳しいアライメント要件です。
- だから
std::alignment_of< std::aligned_storage<BigEnoughNumber>>::value私たちに最大のアライメントを与えるはずです - ドラフトのみで、まだ標準ではありません(あるとしても)、
tr1::aligned_storageこのプロパティはありません
- だから
- default-alignmentの値は、サイズがLen以下のC++オブジェクトタイプの最も厳しいアライメント要件です。
これについての考えもいただければ幸いです。
新しいサブ質問の可視性と入力を増やすために、受け入れられた回答のチェックを一時的にオフにしました