Cメモリ整列の詳細

4055 ワード

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

    int a;

    char b;

    short c;

};


構造体Aには、4バイト長int 1個、1バイト長char 1個、2バイト長short型データ1個が含まれる.したがって、Aが使用する空間は7バイトであるべきである.ただし、コンパイラはデータ・メンバーを空間的に整列させるためです.したがってsizeof(strcut A)の値は8である.この構造体をメンバー変数の順序に調整します.
struct B {

    char b;

    int a;

    short c;

};


このときも合計7バイトの変数ですが、sizeof(struct B)の値は12です.次に、プリコンパイルコマンド#pragma pack(value)を使用して、デフォルトの代わりに指定した位置合わせ値を使用することをコンパイラに伝えます.
#progma pack (2) /*   2    */

struct C {

    char b;

    int a;

    short c;

};

#progma pack () /*      ,      */

//sizeof(struct C)  8。


位置合わせの値を1に変更します.
#progma pack (1) /*   1    */

struct D {

    char b;

    int a;

    short c;

};

#progma pack () /*      ,      */

sizeof(struct D)  7。


 
char型データの場合、自己整列値は1、short型の場合は2、int、float、double型の場合、自己整列値は4、単位バイトです.ここには4つの概念値があります.1)データ型自体の位置合わせ値:上記の基本データ型の自己位置合わせ値です.2)位置合わせ値を指定:#pragma pack(value)の場合の位置合わせ値valueを指定します.3)構造体またはクラスの自己整列値:そのメンバーの自己整列値が最も大きい値.4)データ・メンバー、構造体、クラスの有効な位置合わせ値:自己位置合わせ値と指定位置合わせ値の小さい値.これらの値があれば、特定のデータ構造のメンバーとそれ自体の位置合わせを簡単に議論することができます.有効整列値Nは、最終的にデータ格納アドレスの決定に用いられる値であり、最も重要である.有効整列Nは、「Nに整列する」、すなわち、そのデータの「格納元アドレス%N=0」を表す.データ構造のデータ変数は、定義された順序で排出されます.最初のデータ変数の開始アドレスは、データ構造の開始アドレスです.構造体のメンバー変数は排出を整列させ、構造体自体も自身の有効整列値に基づいて丸めなければならない(すなわち、構造体のメンバー変数が総長を占めるには、構造体の有効整列値の整数倍が必要であり、以下の例に関連して理解される).これで上記のいくつかの例の値を理解するのは難しくありません.例分析:分析例B;
struct B {

    char b;

    int a;

    short c;

};


Bはアドレス空間0 x 0000から排出を開始するものとする.この例では、指定した位置合わせ値は定義されていません.筆者の環境では、この値のデフォルトは4です.第1のメンバ変数bの自己整列値は1である、指定またはデフォルトの指定整列値4よりも小さいため、その有効整列値は1であるため、その格納アドレス0 x 0000が0 x 0000%1=0に該当する.2番目のメンバ変数aは、自身の整列値が4であるため、有効整列値も4であるため、先頭アドレスが0 x 004から0 x 007の4つの連続するバイト空間にしか格納できず、0 x 004%4=0をレビューし、1番目の変数に近い.3番目の変数cは、自己整列値が2であるため、有効整列値も2であり、0 x 008~0 x 009の2バイト空間に格納でき、0 x 008%2=0に適合する.したがって、0 x 0000から0 x 009まではBコンテンツが格納されます.また、データ構造Bの自己整列値は、その変数の中で最大整列値(ここではb)であるので4であるため、構造体の有効整列値も4である.構造体の丸みの要求に応じて、0 x 0009から0 x 0000=10バイト、(10+2)%4=0である.したがって、0 x 0000 A~0 x 000 Bも構造体Bに占有される.したがって、Bは0 x 0000から0 x 000 Bまで12バイトあり、sizeof(struct B)=12である.同様に、上記の例Cを分析する.
#pragma pack (2) /*   2    */

struct C {

    char b;

    int a;

    short c;

};

#pragma pack () /*      ,      */


第1変数bの自己整列値は1であり、指定整列値は2であるため、その有効整列値は1であり、Cが0 x 0000から始まると仮定すると、bは0 x 0000に格納され、0 x 0000%1=0に合致する.2番目の変数は、自己整列値が4、指定整列値が2であるため、有効整列値が2であるため、0 x 002、0 x 003、0 x 004、0 x 005の4つの連続バイトに順次格納され、0 x 002%2=0に合致する.3番目の変数cの自己整列値は2であるため、有効整列値は2であり、0 x 006、0 x 007に順次格納され、0 x 006%2=0に適合する.したがって、0 x 0000から0 x 00007までの8バイトはCの変数を格納する.また、Cの自己整列値は4であるため、Cの有効整列値は2である.また8%2=0であり、Cは0 x 0000から0 x 007までの8バイトしか占有しない.だからsizeof(struct C)=8.以上の説明があり、C言語のバイトアライメントの概念をよく知っていると思います.ネットのプログラムの中で、この概念を掌握するのはとても重要で、异なるプラットフォームの间で(例えばWindowsとLinuxの间で)2進数のストリーム(例えば构造体)を伝达して、それではこの2つのプラットフォームの间で同じ位置合わせの方式を定义しなければならなくて、さもなくばわけがわからないのはいくつか间违いを出して、しかしとても调べにくいです