14

次のような構造定義が与えられます

struct foo {
    int a, b, c;
};

32ビットビルドであっても、常に64ビットアドレスにアラインする必要があることを指定するための最良の(最も単純で、最も信頼性が高く、移植性のある)方法は何ですか?私はGCC4.5.2でC++11を使用しており、Clangもサポートしたいと思っています。

4

6 に答える 6

16

GCCを使用していて、Clangをサポートすることを望んでいると言うので、GCCのaligned 属性でうまくいくはずです。

struct foo {
    int a, b, c;
} __attribute__((__aligned__(8))); // aligned to 8-byte (64-bit) boundary
于 2012-06-08T14:46:52.980 に答える
8

以下は、すべてではありませんが、多くの異なる実装で機能するという意味で、適度に移植可能です。

union foo {
    struct {int a, b, c; } data;
    double padding1;
    long long padding2;
};

static char assert_foo_size[sizeof(foo) % 8 == 0 ? 1 : -1];

次のいずれかを行わない限り、コンパイルに失敗します。

  • コンパイラーは、8の倍数にするためにいくつかのパディングを追加しましfooた。これは通常、アライメント要件の理由でのみ発生します。
  • のレイアウトfoo.dataが非常に奇妙である、または
  • の1つはlong longdouble3 intより大きく、8の倍数です。これは、必ずしも8整列であることを意味するわけではありません。

ただし、サポートする必要があるコンパイラは2つだけであり、clangは設計上かなりgcc互換であるため、__attribute__動作するコンパイラを使用してください。テストしていないコンパイラで(うまくいけば)動作するコードを今すぐ書きたい場合にのみ、他のことを行うことを考えてください。

C ++ 11はalignof、サイズをテストする代わりにテストできるを追加します。誤検知は削除されますが、それでも、ユニオンが必要な配置を作成できず、したがってコンパイルに失敗する、いくつかの準拠した実装が残ります。また、私のsizeofトリックは非常に限られています。構造に3つではなく4つのintがある場合はまったく役に立ちませんが、同じことがalignofあります。gccとclangがサポートしているバージョンがわからないalignofため、最初はそれを使用しませんでした。難しいとは思わなかったでしょう。

ちなみに、のインスタンスfooが動的に割り当てられると、物事は簡単になります。まず、glibcまたは同様mallocの実装はとにかく8整列するのではないかmallocと思います。8バイト整列の基本タイプがある場合は、そうする必要があります。glibcmallocは、存在するかどうかを心配するのではなく、常に実行すると思います。与えられたプラットフォーム。第二に、posix_memalign確かなことがあります。

于 2012-06-08T15:20:01.223 に答える
5

を使用する必要があります__attribute__((aligned(8))。ただし、この説明では、割り当てられた構造のサイズが8バイトの倍数であることを確認するだけであることがわかりました。開始アドレスが複数であることを確認するものではありません。

例えば。私が使用している場合__attribute__((aligned(64))、mallocは開始アドレスが0xed2030である64バイト長の構造体を返す可能性があります。

開始アドレスを整列させたい場合は、aligned_alloc:gccalignedallocationを使用する必要があり ますaligned_alloc(64, sizeof(foo)0xed2040を返します。

于 2016-07-08T06:31:39.477 に答える
2

ポータブル?私は本当にポータブルな方法について本当に知りません。GCCにはが__attribute__((aligned(8)))あり、他のコンパイラにも同等のものがある場合があります。これは、プリプロセッサディレクティブを使用して検出できます。

于 2012-06-08T14:46:23.553 に答える
2

gcc 4.5.2は十分に古く、標準バージョンをまだサポートしていないと確信していますが、C ++ 11では、特にアライメントを処理するためにいくつかのタイプが追加されていますstd::aligned_storagestd::aligned_union詳細については§20.9.7.6を参照してください)。詳細)。

これを行う最も明白な方法は、Boostの実装aligned_storage(または、TR1がある場合はTR1)を使用することだと私には思えます。それを望まない場合でも、ほとんどのコードで標準バージョンを使用することについては一生懸命考えており、標準を実装するコンパイラに更新するまで、自分で使用するために標準バージョンの小さな実装を作成するだけです。__declspec(align...ただし、ポータブルコードは、または__attribute__(__aligned__, ...直接のようなものを使用するほとんどのコードとは少し異なります。

特に、要求されたアラインメントを持つ要求されたサイズのrawバッファーを提供するだけです。その場合、新しい配置のようなものを使用して、そのストレージに同じタイプのオブジェクトを作成するのはあなた次第です。

その価値については、gccのディレクティブにaligned_storage基づくの実装を簡単に説明します。__attribute__(__aligned__,...

template <std::size_t Len, std::size_t Alignment>
struct aligned_storage {
    typedef struct {
        __attribute__(__aligned__(Alignment)) unsigned char __data[Len];
    } type;
};

これを使用する方法を示すための簡単なテストプログラム:

struct foo {
    int a, b, c;

    void *operator new(size_t, void *in) { return in; }
};

int main() {
    stdx::aligned_storage<sizeof(foo), 8>::type buf;

    foo& f = *new (static_cast<void*>(&buf)) foo();

    int address = *reinterpret_cast<int *>(&f);

    if (address & 0x3 != 0)
        std::cout << "Failed.\n";

    f.~foo();

    return 0;
}

もちろん、実際の使用では、ここで示した醜さのほとんどをまとめて非表示にします。このままにしておくと、(理論的/将来の)携帯性の価格はおそらく高すぎるでしょう。

于 2012-06-08T15:39:17.460 に答える
1

[[gnu::aligned(64)]] in c++11 annotation std::atomic <int64_t> ob [[gnu::aligned(64)]]

于 2018-09-06T03:44:21.557 に答える