11


3

C 64ビットポインターの配置

64ビットシステムのポインターはまだ4バイトにアライメントされていますか(32ビットシステムのダブルに似ています)? または、8バイトに揃えられていることに注意していますか?

たとえば、64ビットシステムでは、次のデータ構造の大きさはどれくらいですか。

struct a {
    void* ptr;
    char myChar;
}

ポインターを8バイトに揃えて、文字のパディングを7バイトにします(合計= 8 + 8 = 16)。 または、ポインターが4バイトにアライメントされ(4バイト+ 4バイト)、3バイトのパディングが発生します(合計= 4 + 4 + 4 = 12)。

ありがとう、ライアン

5 Answer


6


私はあなたがどんな厳格なルールにも頼ることができるとは思わない。 これは、使用するコンパイラと選択するコンパイルオプションの機能だと思います。

あなたの最善の策は、これをテストし、整列規則を「#define」として成文化するヘッダーファイルを吐き出すプログラムを書くことです。 また、マクロ内で興味のあることを計算することもできます。


6


データのアライメントとパッキングは実装固有であり、通常はコンパイラ設定から(またはプラグマを使用して)変更できます。

ただし、デフォルト設定を使用していると仮定すると、ほとんどの(すべてではないにしても)コンパイラーでは、構造は合計16バイトになります。 その理由は、コンピューターがネイティブワードサイズ(64ビットシステムでは8バイト)のサイズでデータチャンクを読み取るためです。 4バイトオフセットにパディングすると、次の構造は64ビット境界に適切にパディングされません。 たとえば、arr [2]の場合、配列の2番目の要素は、マシンのネイティブのバイト境界ではなく、12バイトのオフセットで始まります。


3


通常、64ビットシステムの場合:

struct a {
    void* ptr;      // size is 8 bytes, alignment is 8
    char myChar;    // size is 1 byte,  alignment is 1
                    // padding of 7 bytes so array elements will be properly aligned
}

合計サイズが16バイトの場合。

しかし、これはすべて定義された実装です-多くの(ほとんどの?)64ビットシステムに当てはまる可能性が高い例を挙げています。


1


言語標準では、パディングに関する記述はありません。 アライメントルールはプラットフォーム固有です(つまり、異なる方法でアライメントする必要があります。 (x86_64 CPUよりもPowerPC CPU)、およびそれらは実装定義です。つまり、コンパイラーは何でも機能します(異なるコマンドラインオプションまたはバージョン更新後にその動作を変更する可能性があります)。

「これは「通常」これまたはそれである」という行に沿った_任意の推奨は誤解を招く可能性があり、おそらく危険であると強く信じています。

  1. いくつかの `sizeof()`を実行するテストプログラムを書くことができます および/または `offsetof()`ステートメントを使用し、使用するパディングを示すいくつかの `#define`を含むヘッダーを書き込みます。

  2. `autoconf`を使用してそれを行うことができます。

  3. 少なくとも、 `assert(sizeof(…​ )) `ステートメント `main()`関数の先頭で、仮定が間違っているときに通知されるようにします。


0


興味のある特定のABIのドキュメントを参照する必要があります。 たとえば、http://www.x86-64.org/documentation/abi.pdf [System V ABI x86-64アーキテクチャサプリメント]-12ページで、このABIのポインターが8バイトにアライメントされていることがわかります。 (したがって、はい、表示する構造は16バイトに埋め込まれます)。