1

サイズが 48 バイトの構造体があり、最近、その内部にサイズが 20 バイトの別の構造体を追加しました。したがって、構造体の合計サイズは 68 バイトになりました。(すべてのメンバーは unsigned int でした)

typedef struct{
           ...
           ...
           unsigned long long a1;
           struct s2
           }s1 ;

S1 構造体は配列です。s1++ を使用して s1 をインクリメントすると、s1 が 68 バイトではなく 72 バイトでインクリメントされることが観察されます。驚くべきことに、構造体 s2 が s1 から削除された場合、すべてが適切に機能します。つまり、s1 は 48 バイト増加します。理由についての指針は役に立ちます。

4

3 に答える 3

3

使用しているコンパイラまたはプラットフォームはわかりませんが、おそらくコンパイラは、構造体を8バイト境界に整列させるために整列バイトを追加しています。これは非常に一般的です。

于 2012-05-24T14:25:41.010 に答える
1

起こっているのは構造パディングです。

これは、要素がアラインされたメモリ アドレスに存在することを保証するために、コンパイラによって行われます。

x86/x86_64 の「アライメント」について詳しくは、こちらをご覧ください。

では、なぜそれらはアラインされたアドレスにある必要があるのでしょうか? (例として 4 バイトの WORD を使用):マシンはメモリからのデータに「ワード」でアクセスします。4 バイトの WORD の場合、これは、アドレスから 1 バイトを読み取るには、b110011104 バイトを読み取る必要があることを意味します (アドレスの最後の 2 ビットは基本的に、読み取り中に無視されます)。次に、必要なバイトを 1 回選択します。 WORDはCPUにあります:

| b11001100 | b11001101 | b11001110 | b11001111 |    <- all four loaded at once
                        \           /
                        only one used

より大きなデータ型の読み取りを開始すると、「整列されていない」データムの読み取りは、整列されたデータムの読み取りよりもコストがかかる可能性があります。

1 バイトだけではなく、アドレスから 4 バイト (1 WORD) をb01110読み取る場合は、2 WORDS を読み取る必要があります。

        first load             second load
/                       \/                      \
|01100|01101|01110|01111|10000|10001|10010|10011|
            \                       /
               unaligned data read

コンパイラは、このような読み取りを避けるために構造を「パディング」します。コストがかかるからです。Woodrow Douglass が回答で示唆しているように、コンパイラに「パッド」ではなく「パック」を強制できます。

もう 1 つ: アラインされていないロードが不可能なアーキテクチャもあります。このようなマシンでは、通常、オペレーティング システムは非整列ロード中に発生した例外をキャッチし、何らかの方法で (たとえば、複数の整列ロードを実行することによって) ロードをシミュレートします。

于 2012-05-24T14:48:58.683 に答える
-1

これは64ビットマシンですか?72 バイトは 64 ビットのワード境界です。コンパイラが構造を調整しています。gcc では、構造体を で宣言すると__attribute__((__packed__))、これを回避できます。

したがって、次のように typedef を宣言します。

typedef struct {
    ...
    ...
    struct s2;
} __attribute__((__packed__)) s1;
于 2012-05-24T14:26:14.597 に答える