C言語構造体——sizeof(struct)

5145 ワード

この内容も重要なので、ここではいくつかの問題と法則をまとめます.
関連するいくつかの概念:
メモリの位置合わせ:
現代のコンピュータではメモリ空間はbyteによって区分されており、理論的には任意のタイプの変数へのアクセスは任意のアドレスから開始できるようだが、実際には特定の変数にアクセスする際に特定のメモリアドレスにアクセスすることが多い.これは、順番の排出ではなく、一定の規則に従って空間に配置する必要がある.これが位置合わせです. 
配置の役割と理由:
各ハードウェアプラットフォームは、ストレージスペースの処理に大きな違いがあります.一部のプラットフォームでは、特定のタイプのデータに対して、特定のアドレスからのみアクセスできます.他のプラットフォームではこのような状況はないかもしれませんが、最も一般的なのは、プラットフォームに適した要件に従ってデータの保存を整列しないと、アクセス効率に損失をもたらすことです.例えば、読むたびに偶数アドレスから始まるプラットフォームもあります.1つのint型(32ビットシステムと仮定)が偶数アドレスの先頭に格納されていれば、1つのリードサイクルが読み出され、奇アドレスの先頭に格納されていれば、2つのリードサイクルが必要になり、2回の読み出しの結果の高低バイトをパッチワークしてそのintデータが得られる可能性がある.明らかに、読み出し効率が大幅に低下する.
配置の実装:
通常、私たちがプログラムを書くときは、位置合わせの問題を考慮する必要はありません.コンパイラは、ターゲットプラットフォームに適した位置合わせポリシーを選択します.もちろん、コンパイラにプリコンパイル命令を渡すことを通知して、指定したデータの位置合わせ方法を変更することもできます.
しかし、私たちは一般的にこの問題に関心を持つ必要がないだけに、エディタがデータの保存を位置合わせしているので、私たちが知らないと、いくつかの問題に戸惑うことがよくあります.最も一般的なのはstructデータ構造のsizeof結果であり,予想外であった.このため、位置合わせアルゴリズムについて理解する必要があります.
整列アルゴリズム
     
各プラットフォームとコンパイラの違いにより、本人が使用するgcc version 4.3.2コンパイラ(32ビットx 86プラットフォーム)を例に、structデータ構造の各メンバーをコンパイラがどのように位置合わせするかを議論します.このプラットフォームは偶数アドレスで読み取りが開始されます.
構造体の定義は次のようになります.
struct SA
{
     int a;
     char b;
     short c;
};

構造体SAには、4 Byte長のint、1 B yte長のchar、2 Byte長のshortが含まれる.ではSAが使う空間は7 Byteのはずですが、sizeof(SA)の結果は8です.これは、コンパイラがデータ・メンバーを空間的に整列しているためです.
次はSAのメンバー順を調整します.
struct SB
{
     char b;
     int a;
     short c;
};

我々のこれまでの解析ではSBの空間サイズも7 Byteであるべきであったが,sizeof(SB)の結果は12であった.
ただ順番が少し調整されているだけなのに結果が大きくずれているのはなぜでしょうか?コンパイラが手足を作ったからです.次に、プリコンパイルコマンド#pragma pack(value)を使用して、デフォルト値の代わりにコンパイラが指定した位置合わせ値を使用して、私たちの考えに従って仕事をさせます.
#pragma pack (1) /*    1Byte   */
struct SC
{
     char b;
     int a;
     short c;
};
#pragma pack () /*       ,       */

次に、
プリコンパイルコマンド#pragma pack(value)は、デフォルト値の代わりにコンパイラが指定した位置合わせ値を使用して、私たちの考えに従って仕事をするようにします.
このときsizeof(SC)の結果は:7であった.
もう一度テストを行います.
#pragma pack (2) /*    2Byte   */
struct SD
{
     char b;
     int a;
     short c;
};
#pragma pack () /*       ,       */

このときsizeof(SD)の結果は:8であった.
実は、ここにはいくつかの概念があります.
値:
1.データ型の自己整列値:基本データ型の自己整列値:
char型データの場合、自己整列値は1、short型の場合は2、int、float型の場合、自己整列値は4単位バイト、double型の場合は8です.
2.位置合わせ値の指定:#progma pack(value)の場合の位置合わせ値valueの指定.  3.構造体またはクラスの自己整列値:メンバーの自己整列値が最も大きい値.  4.データ・メンバー、構造体、クラスの有効な整列値:自己整列値と指定した整列値のうちの値.
ここで、有効整列値Nは、最終的にデータ格納アドレスの決定に用いられる値であり、最も重要である.
(1)有効な位置合わせNは、「Nに位置合わせ」を示す、すなわち、そのデータの「格納元アドレス%N=0」である.
(2)データ構造におけるデータ変数は、定義された前後順に排出される.第1のデータ変数の先頭アドレスは、データ構造の先頭アドレスである.
(3)構造体のメンバー変数は排出を整列させ、構造体自体も自身の有効整列値に基づいて丸めなければならない.すなわち、構造体のメンバー変数が総長を占めるには、構造体の有効整列値の整数倍が必要である.
これでは上記のいくつかの例の値が理解できません.
例分析:
構造体SBについて
struct SB
{
     char b;
     int a;
     short c;
};

SBがアドレス0 x 0000から排出を開始すると仮定すると、このとき位置合わせ値が指定されておらず、本人のデフォルトは4である.
最初のメンバー変数bは、自身の位置合わせ値が1であり、指定またはデフォルトが4であり、小さい場合、bの有効な位置合わせ値は1である.
したがって、その格納アドレス0 x 0000は0 x 0000%1=0に合致する.
2番目のメンバー変数aは、自身の位置合わせ値が4であり、
指定またはデフォルトが4の場合、aの有効な整列値は4であるため、aは0 x 004-0 x 007という連続する4バイト空間にしか格納できず、一致する
0x0004%4=0
最初の変数に近いです.
3番目のメンバー変数cは、自身の位置合わせ値が2であるため、cの有効な位置合わせ値は2である.0 x 008-0 x 009の2つの連続したバイト空間に格納することができ、0 x 008%2=0に合致する.
したがって、0 x 0000−0 x 0009には、構造体SBの内容が格納される.
データ構造SB自身の位置合わせ値(
メンバーの自己位置合わせ値が最も大きい値)
ここではaなのでSB自体の有効整列値は4となる.構造体丸みによれば、0 x 0000−0 x 0009は10バイトであり、(10+2)%4=0であるため、0 x 000 A−0 x 000 Bも構造体SBに占有される.
したがって、Bは0 x 0000から0 x 000 Bまで12バイトあり、sizeof(SB)=12である.
同様に、構造体SCについては、
#pragma pack (1) /*    1Byte   */
struct SC
{
     char b;
     int a;
     short c;
};
#pragma pack () /*       ,       */

私たち自身が有効値を指定したので、各有効値は1です.SCが0 x 0000から格納とすると、変数b、a、cのアドレスは、0 x 0000、0 x 001-0 x 0004、0 x 005-0 x 006の順である.全部で7 byteあります.
sizeof(SC)=7.
構造体SDの場合:
#pragma pack (2) /*    2Byte   */
struct SD
{
     char b;
     int a;
     short c;
};
#pragma pack () /*       ,       */

SDがアドレス0 x 0000から排出を開始すると仮定し、このとき自己指定位置合わせ値は4とする.
最初のメンバー変数bは、自身の位置合わせ値が1であり、指定された位置合わせ値が2であり、小さいものをとると、bの有効な位置合わせ値が1である.
したがって、その格納アドレス0 x 0000は0 x 0000%1=0に合致する.
2番目のメンバー変数aは、自身の位置合わせ値が4であり、
指定された位置合わせ値が2の場合、aの有効位置合わせ値は2のため、aは0 x 002-0 x 0005の連続する4バイト空間にしか格納できず、一致する
0x0002%2=0
最初の変数に近いです.
3番目のメンバー変数cは、自身の位置合わせ値が2であり、
指定した位置合わせの値は2です.
したがって、cの有効な位置合わせ値は2である.0 x 006-0 x 007の2つの連続するバイト空間に格納することができ、0 x 006%2=0に適合する.
したがって、0 x 0000−0 x 0007には、構造体SBの内容が格納される.
データ構造SB自身の位置合わせ値(
メンバーの自己位置合わせ値が最も大きい値)
ここではaなのでSB自体の有効整列値は4となる.構造体丸みによる、0 x 0000-0 x 0007は8バイトであるのに対し、構造体SD自体の位置合わせ値は4である
したがって、SCの有効な位置合わせ値は2であり、
一方、8%2=0です.
したがって、Bは0 x 0000から0 x 007まで8バイトあり、sizeof(SD)=12である.
上の分析から次の法則をまとめることができます.
1)構造体の各変数の自己整列値を、指定またはデフォルトの整列値と比較して、そのメンバー変数の「有効整列値」として比較する.
2)次に、(アドレス%N)=0に基づいて、各メンバー変数の記憶アドレス(Nが有効な位置合わせ値である)を決定する.
3)各メンバー変数の記憶アドレスを決定した後、構造体自身の位置合わせ値を見る.
メンバーの自己整列値が最も大きい値も、同じです.
この構造体の「有効な位置合わせ値」として、両者の小さいものを取ります.
再根拠
こうぞうえんせい
この構造体が全部で何バイトの空間の大きさを占有したかを求めます
.
埋め込み式に进出して、みんなで交流して、共に进歩します!!!