0

さて、私が本当に興味を持っていたものに答えが得られなかったので、質問を再質問させてください(このような質問の全体規模の編集が偽物である場合は申し訳ありません).

いくつかのポイント:

  • これは、私がテストしているものとは異なるコンパイラを使用したオフライン分析であるため、SIZEOF() などは私が行っていることでは機能しません。
  • 私はそれが実装定義であることを知っていますが、私が興味を持っている実装をたまたま知っています。

アライメントと呼ばれる整数と、要素と呼ばれる整数のタプルを入力として取る pack と呼ばれる関数を作成しましょう。サイズと呼ばれる別の整数を出力します。

この関数は次のように機能します。

int pack (int alignment, int[] elements)
{
  total_size = 0;

  foreach( element in elements )
  {
    while( total_size % min(alignment, element) != 0 ) { ++total_size; }
    total_size += element;
  }

  while( total_size % packing != 0 ) { ++total_size; }

  return total_size;
}

私が聞きたいのは、「この関数の逆関数は何ですか?」ということだと思いますが、逆関数という用語が正しいかどうかはわかりません。複数の入力を持つ関数の逆関数を扱った覚えがないので、当てはまらない用語を使用している可能性があります。

私が欲しいもの(のようなもの)が存在します。ここで、determine_align と呼ぶ関数の疑似コードを提供します。ただし、この関数は少しナイーブです。期待する (または失敗する) 応答が得られるまで、さまざまな入力を使用して pack を何度も呼び出すだけだからです。

int determine_align(int total_size, int[] elements)
{
  for(packing = 1,2,4,...,64) // expected answers.
  {
    size_at_cur_packing = pack(packing, elements);

    if(actual_size == size_at_cur_packing)
    {
      return packing;
    }
  }

  return unknown;
}

問題は、determine_align のより良い実装があるかどうかです。

ありがとう、

4

7 に答える 7

7

C/C++ での構造体メンバーのアライメントは、完全に実装定義です。そこにはいくつかの保証がありますが、それらがどのように役立つかわかりません.

したがって、あなたが望むことを行うための一般的な方法はありません。特定の実装のコンテキストでは、これをカバーするその実装のドキュメントを参照する必要があります (カバーされている場合)。

于 2009-08-15T00:03:55.493 に答える
5

メンバーを実装にパックする方法を選択するときstruct、アルゴリズムで記述したようなスキームに従う必要はありませんが、それは一般的なものです。(つまり、アラインされる型の最小サイズと、優先されるマシン アラインメント サイズ)。

ただし、個々のメンバーにstruct適用されたパディングを判断するために、全体のサイズを比較する必要はありません。struct標準マクロは、個々の構造体メンバーoffsetofの先頭からのバイト オフセットを提供します。struct

于 2009-08-15T00:24:21.227 に答える
3

コンパイラーにアライメントを任せます。

gcc では、

typedef struct _foo
{
    u8 v1  __attribute__((aligned(4)));
    u16 v2 __attribute__((aligned(4)));
    u32 v3 __attribute__((aligned(8)));
    u8 v1  __attribute__((aligned(4)));
} foo;

編集: sizeof(foo) はパディングを含む正しい値を返すことに注意してください。

Edit2: そして、offsetof(foo, v2) も機能します。これら 2 つの関数/マクロがあれば、メモリ内の構造体のレイアウトについて知る必要があるすべてを把握できます。

于 2009-08-15T00:01:22.097 に答える
0

次のフィールドの配置に基づいてパディングし、構造体で見た最大の配置に基づいて最後の要素をパディングする必要があります。フィールドの実際のアラインメントは、その自然なアラインメントとその構造体のパッキングの最小値であることに注意してください。つまり、構造体が 4 バイトでパックされている場合、double は、本来の位置合わせが 8 であっても、4 バイトに位置合わせされます。

を使用して内部ループを高速化できます。 andが 2 のべき乗であるtotal_size+= total_size % min(packing, element.size);場合は、さらに最適化できます。packingelement.size

于 2009-08-15T00:02:54.043 に答える
0

問題が特定のアライメントを保証したいということだけであれば、それは簡単です。特定の配置 = 2^n の場合:

void* p = malloc( sizeof( _foo ) + alignment -1 );
p = (void*) ( ( (char*)(p) + alignment - 1 ) & ~alignment );

malloc から返された元の p に保存することを怠っています。このメモリを解放する場合は、そのポインタをどこかに保存する必要があります。

于 2009-08-15T01:54:16.297 に答える
0

ここで何を達成したいのかわかりません。Pavel Minaevが言ったように、アラインメントはコンパイラによって処理されます。コンパイラは、別のコンパイラによってコンパイルされたコードにアクセスできるようになるデータに対して、プラットフォームのアプリケーション バイナリ インターフェイスによって制約されます。次の論文では、呼び出し規約を実装する必要があるコンパイラのコンテキストで問題について説明しています。

クリスチャン・リンディグとノーマン・ラムジー。スタック フレームの宣言的構成。Evelyn Duesterwald、編集者、Proc。コンパイラ構築に関する第 14 回国際会議、Springer、LNCS 2985、2004 年。

于 2012-12-27T17:26:41.650 に答える