2

私は次の2つの構造体を持っています:

問題は、sizeof(Content)が160を返すことです。構造体は、11個のshort、6個のint、76個のchar、7個のfloat、1個のdoubleで構成され、合計で158バイトになります。私は3回カウントしましたが、まだ2バイトの違いがあります。

typedef struct TIME_T { 
    short year,mon,day; 
    short hour,min,sec; 
} TIME;

typedef struct { 
    int no; 
    char name[20]; 
    char Code[10]; 
    char DASType[10]; 
    short wlen; 
    float VLtd; 
    int samp; 
    int comp; 
    int locationID; 
    short TranMode; 
    char TranIns[12]; 
    short TimerMode; 
    char ClkType[12]; 
    float ClkErr; 
    float lat; 
    float lon; 
    float alt; 
    float azimuth,incident; 
    short weight; 
    short veloc; 
    int oritype; 
    char seismometer[12]; 
    double sens; 
    TIME start_time; 
    int record_samples; 
} Content;

構造体の各変数の位置を出力するための小さなコードを記述しましたが、突然float wlen4バイトかかることがわかりました。私のコードは次のとおりです。

int main(void)
{   
    Content content;
    printf("Sizeof Content: %d\n", sizeof(content));
    printf("Sizeof int content.no: %d\n", (int)&content.name - (int)&content.no);
    printf("Sizeof char[20] content.name: %d\n", (int)&content.Code - (int)&content.name);
    printf("Sizeof char[10] content.Code: %d\n", (int)&content.DASType - (int)&content.Code);
    printf("Sizeof char[10] content.DASType: %d\n", (int)&content.wlen - (int)&content.DASType);
    printf("Sizeof short content.wlen:  %d\n", (int)&content.VLtd - (int)&content.wlen);
    printf("Sizeof float content.VLtdL %d\n", (int)&content.samp - (int)&content.VLtd);
    printf("Sizeof int content.samp: %d\n", (int)&content.comp - (int)&content.samp);
    printf("Sizeof int content.comp: %d\n", (int)&content.locationID - (int)&content.comp);
    printf("Sizeof int content.locationID: %d\n", (int)&content.TranMode - (int)&content.locationID);
    printf("Sizeof short content.TranMode: %d\n", (int)&content.TranIns - (int)&content.TranMode);
    printf("Sizeof char[12] content.TranIns: %d\n", (int)&content.TimerMode - (int)&content.TranIns);
    printf("Sizeof short content.TimerMode: %d\n", (int)&content.ClkType - (int)&content.TimerMode);
    printf("Sizeof char[12] content.ClkType: %d\n", (int)&content.ClkErr - (int)&content.ClkType);
    printf("Sizeof float content.ClkErr: %d\n", (int)&content.lat - (int)&content.ClkErr);
    printf("Sizeof float content.lat: %d\n", (int)&content.lon - (int)&content.lat);
    printf("Sizeof floatcontent.lon: %d\n", (int)&content.alt - (int)&content.lon);
    printf("Sizeof floatcontent.alt: %d\n", (int)&content.azimuth - (int)&content.alt);
    printf("Sizeof floatcontent.azimuth: %d\n", (int)&content.incident - (int)&content.azimuth);
    printf("Sizeof floatcontent.incident: %d\n", (int)&content.weight - (int)&content.incident);
    printf("Sizeof short content.weight: %d\n", (int)&content.veloc - (int)&content.weight);
    printf("Sizeof short content.veloc: %d\n", (int)&content.oritype - (int)&content.veloc);
    printf("Sizeof int content.oritype: %d\n", (int)&content.seismometer - (int)&content.oritype);
    printf("Sizeof char[12] content.seismometer: %d\n", (int)&content.sens - (int)&content.seismometer);
    printf("Sizeof double content.sens: %d\n", (int)&content.start_time - (int)&content.sens);
    printf("Sizeof TIME content.start_time: %d\n", (int)&content.record_samples - (int)&content.start_time);
    printf("Sizeof int content.record_samples: %d\n", sizeof(content.record_samples));

    getchar();
    return 0;
}

出力は次のとおりです。

Sizeof int content.no: 4
Sizeof char[20] content.name: 20
Sizeof char[10] content.Code: 10
Sizeof char[10] content.DASType: 10
Sizeof short content.wlen:  4
**Sizeof float content.VLtdL 4**
Sizeof int content.samp: 4
Sizeof int content.comp: 4
Sizeof int content.locationID: 4
Sizeof short content.TranMode: 2
Sizeof char[12] content.TranIns: 12
Sizeof short content.TimerMode: 2
Sizeof char[12] content.ClkType: 12
Sizeof float content.ClkErr: 4
Sizeof float content.lat: 4
Sizeof floatcontent.lon: 4
Sizeof floatcontent.alt: 4
Sizeof floatcontent.azimuth: 4
Sizeof floatcontent.incident: 4
Sizeof short content.weight: 2
Sizeof short content.veloc: 2
Sizeof int content.oritype: 4
Sizeof char[12] content.seismometer: 12
Sizeof double content.sens: 8
Sizeof TIME content.start_time: 12
Sizeof int content.record_samples: 4

コンパイラはMSVC8であり、UNICODEは定義されておらず、他のマクロも定義されていません。x86です。

gccバージョン3.4.4で同じコードをコンパイルしようとしましたが、出力は同じです。 Sizeof short content.wlen: 4

誰かが私にこれを説明できますか?

前もって感謝します。

編集:答えてくれてありがとう!私は今それを持っています。

4

9 に答える 9

23

短い答えのみ:配置

于 2009-05-07T08:50:47.900 に答える
11

構造体のすべてのコンポーネントのサイズを単純に加算するだけでは、構造体のサイズを計算することはできません。コンパイラは、フィールド間にパディングを挿入することが許可されており、頻繁に実行されます。

于 2009-05-07T08:51:23.297 に答える
4

アライメント — 32 ビット アーキテクチャでは、メモリを 32 ビット チャンクで渡す方がはるかに効率的です。short を 16 ビットで格納しても、関連する 32 ビット ワードの一部であるため、実際にはメモリをまったく節約できません。

于 2009-05-07T08:53:21.887 に答える
3

フィールドのサイズではなく、それらの間の「距離」を計算しているので、構造体内の単語の配置が表示されていると思います。

于 2009-05-07T08:53:21.077 に答える
3

構造に別のショートを追加すると、サイズが拡張されますか、それとも同じままですか? 私の賭けは、それが同じサイズのままであることです.

両方のコンパイラは、構造を 8 バイトに揃えるために動作しているため (私は推測します)、一部のフィールドは「拡張」されて余分なスペースを占有します。そのフィールドに対する実際の操作は、「適切な」サイズであるかのように動作します。

于 2009-05-07T08:53:55.053 に答える
3

構造体のメンバーは、多くの場合、アクセスがより便利であるとコンパイラが判断した場合、4 バイト境界に整列されます。同様の動作が char でも発生します。

2 つの連続する short が 1 つの 32 ビット ワードを使用するように、short を組み合わせることで、構造体のメモリ フットプリントを最適化することができます。コンパイラの結果を再確認することを忘れないでください。

于 2009-05-07T09:00:54.647 に答える
2

dfaが言ったように、それはアライメントによるものです。構造のサイズを縮小するのに役立つ「グッドプラクティス」の1つは、最大のメンバーから順に、個々のサイズ(実際には個々の配置ですが、サイズは十分な場合があります)でメンバーを並べ替えることです。

これは常に正しいとは限りませんが、ほとんどの場合です。

于 2009-05-07T09:31:29.003 に答える
2

C 標準によると、メモリ内のすべてのネイティブ型はそのサイズに合わせて配置する必要がありますが、問題には直接関係しません。調べる必要があるのは、構造体のパッキングです。

于 2009-05-07T09:06:04.493 に答える
1

Poke-a-Hole の略である pahole を見てみましょう。これは、構造体の穴を見つけるために使用される DWARF2 ツールの 1 つです。穴とは、整列規則のためにメンバー間のスペースであり、新しい構造体エントリに使用したり、サイズを縮小するために再編成したりできます。

詳細については、プログラムの作成者である Arnaldo Carvalho de Melo によるLWN の記事を参照してください。

ネット上には多くのチュートリアルはありませんが、CERN のこの wiki ページは多少役に立ちます。

于 2009-05-07T09:08:47.030 に答える