2009-05-07 8 views
2

Iは、次の2つの構造体を有する:shortはCの構造体に4バイトとして格納されるのはなぜですか?

問題ははsizeof(コンテンツ)160を構造体11のショーツ、6つのint型、76文字、7台のフロート、ダブル1、全く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; 

Iは、構造体の各変数の位置を印刷するコードの小片を書き、そして突然私はfloat wlen 4つのバイトを取る見つけます。次のように私のコードは次のよう

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

誰でもこのことを私に説明できますか?

ありがとうございます。

編集:お返事ありがとうございます!私は今それを持っている。唯一

+0

ここを参照してください:http://stackoverflow.com/questions/713963/why-does-this-c-code-workデータメンバのオフセットを計算するマクロ。それは別の議論でしたが、マクロは作業をしています... –

+0

sizeofによって返されるサイズは%dで印刷しないでください。型si size_tは、一般にunsigned intまたはunsigned longのtypedefです。 "%u"、(unsigned int)sizeof(...)、 "%lu \ n"、(unsigned long)sizeof(%s)を使用する前にキャストする必要があります。 ...)。 C99にsize_t形式が追加されていると思います。 –

答えて

11

あなたは、単にそのすべてのコンポーネントのサイズを追加することにより、構造体のサイズを動作することはできません - コンパイラは、フィールド間にパディングを挿入することができ、そして頻繁にしています。

3

あなたはフィールドのサイズではなく、それらの間の "距離"を計算しているので、あなたが見ているのは、構造体内の単語の位置合わせです。

4

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

+0

通常、構造体の2つの隣接するshortは、パディングを使用して各メンバーを「自然な」配置にする通常の規則と同じようにパックされます。もちろん、すべての問題は実装定義の動作であるため、あなたの走行距離はかなり変わります。 – RBerteig

3

構造をもう一度短くするとサイズが拡大されますか、それとも同じに保たれますか?私の賭けは同じサイズのままです。

どちらのコンパイラも構造体を8バイトに整列させようとしています(私は推測しています)ので、余分な部屋を占めるためにいくつかのフィールドが "拡張"されます。そのフィールドの実際の操作は、あたかも「正しい」サイズであるかのように動作します。

+0

既存のパディングバイトを再利用できるように、新しいshortがwlenメンバーに隣接して挿入されている場合に限り、同じサイズを維持する可能性があります。他の場所にそれを挿入すると、2つ以上のパディングバイトが発生する可能性があります。 – RBerteig

3

構造メンバーは、アクセスがより便利になるとコンパイラが検出した場合、しばしば4バイトの境界に整列されます。 charと同様の動作が発生します。

ショートをまとめて2つの連続した短絡が1つの32ビットワードを使用するようにすることで、構造のメモリフットプリントを最適化することができます。コンパイラの結果を二重にチェックすることを忘れないでください。

2

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

1

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

this LWN articleのプログラムについては、Arnaldo Carvalho de Meloの作者が詳しく説明しています。

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

2

dfaが述べたように、それは整列によるものです。構造体のサイズを小さくするのに役立つ1つの「良い方法」は、個々のサイズ(実際には個々の配置ですが、サイズはしばしば十分です)でメンバーを注文することです。

これは必ずしも真実ではなく、ほとんどの場合です。

関連する問題