Cバイト整列

10025 ワード

一、バイト整列作用と原因:整列作用と原因:各ハードウェアプラットフォームは記憶空間の処理に大きな違いがある.一部のプラットフォームでは、特定のタイプのデータに対して、特定のアドレスからのみアクセスできます.例えば、一部のアーキテクチャのCPUは、整列されていない変数にアクセスする際にエラーが発生する場合があります.このアーキテクチャの下でプログラミングするにはバイト整列を保証する必要があります.他のプラットフォームではそうではない可能性がありますが、最も一般的なのは、プラットフォームに適した要求に従ってデータの格納を整列させないと、アクセス効率に損失をもたらすことです.例えば、読むたびに偶数アドレスから始まるプラットフォームがあり、int型(32ビットシステムと仮定)が偶数アドレスから始まる場所に格納されていれば、1つのリードサイクルで32 bitを読み出すことができ、奇数アドレスから始まる場所に格納されている場合、2つのリードサイクルが必要となり、2回のリード結果の高低バイトをパッチワークして32 bitデータを得ることができる.明らかに読み取り効率が大幅に低下している.
 
三、基本概念
バイト整列:コンピュータストレージシステムではByte単位でデータを格納し、異なるデータ型が占める空間が異なります.例えば、整数(int)データが4バイト、文字型(char)データが1バイト、短整数(short)データが2バイトなどです.コンピュータは、高速な読み書きデータのために、デフォルトでは、あるアドレスの開始位置にデータを格納する.例えば、整数データ(int)は、アドレスが4で割り切れる開始位置にデフォルトで格納され、文字型データ(char)は、任意のアドレス位置(1で割り切れる)に格納され、短い整数データは、アドレスが2で割り切れる開始位置に格納される.これがデフォルトのバイト位置合わせです.
四、構造体の長さの求め方
1.メンバーが同じ(または配列を含み、配列データ型が構造体の他のメンバーデータ型と同じ):構造体長=メンバーデータ型長×メンバーの数(各メンバーの長さの和);構造体における配列長=配列データ型長×配列要素の個数;
2.メンバーが異なり、他の構造体が含まれていない場合.(1).各メンバーの長さを分析します.(2).最大長のメンバー長M(構造体の長さは必ずそのメンバーの整数倍)を探し出す.(3).最大メンバー長が現れる位置で構造体をいくつかの部分に分けます.(4).各部分の長いを一度に加算、その和よりも大きい最小Mの整数倍が当該部分の長さ(5)となるように求める.各部分の長さの合計を足すと構造体の長さになります
3.その他の構造体を含む場合:(1).各メンバーの長さを分析します.(2).対は構造体のメンバーであり、その長さはbで分析され、位置の変化に伴って変化しない.(3).各メンバーの長さ(メンバーが構造体である分析メンバーの長さ)を分析し、最大値を求める.(4).最大長のメンバーが構造体のメンバーにある場合、構造体のメンバーによって境界点として境界されます.他のメンバーに最大長のメンバーがある場合、そのメンバーは境界点です.各セグメントの長さを求める、その和より大きい最小Mの整数倍を求める、その部分の長さ(5)とする.各部分の長さの合計を足すと構造体の長さになります
 
 
 
七、例を挙げて説明する
1.例1
デフォルトの位置合わせでは、次のような構造のような多くのスペースが浪費されることは明らかです.
struct student 
{ 
    char name[5]; 
    int num; 
    short score; 
}

は11 bytes(5+4+2)のスペースしか われていなかったが、int のデフォルト4バイト のため、アドレスが4で り れる 、すなわちname[5]が0から されると5 bytesを め、numは8(オフセット )バイト から される.したがってsizeof(student)=16です.そこで バイトか けておいた.しかし、このようにコンピュータがデータを に み きするのに で、 で を する です.データは のように されます.
|char|char|char|char| 
|char|----|----|----| 
|--------int--------| 
|--short--|----|----| 

の の を のように します.
struct student 
{ 
    int num; 
    char name[5]; 
    short score; 
}

するとnumは0から され、nameは4(オフセット )バイト から され、5バイト でscoreは10(オフセット ) から されるのでsizeof(student)=12となる.データは のように されます.
|--------int--------| 
|char|char|char|char| 
|char|----|--short--| 

の の を のように します.
struct student 
{ 
    int num; 
    short score; 
    char name[5]; 
}

では、sizeof(student)=12になります.データは のように されます.
|--------int--------| 
|--short--|char|char| 
|char|char|char|----| 

2. 2
(1)
struct test1 
  { int a; 
   int b[4]; 
  };

sizeof(test1)=sizeof(int)+4*sizeof(int)=4+4*4=20;
(2)
 struct test2 
  { char a; 
   int b; 
   double c; 
   bool d; 
  };

:この の double 、 さは8であるため、 の さは2つの に けられる: 1 はa、b、cの さと、 さはそれぞれ1、4、8で、この の さと13で、8の13より きい は16である. 2の はdであり、 さは1であり、1より きい8の は8であり、2つの と24であるためsizeof(test 2)=24である.
(3)
 struct test3 
{ 
 char a; 
 test2 bb;//    
 int cc; 
}

:この には3つのメンバーがあり、そのうち2 のbbはtest 2の であり、 さは24であり、この の メンバータイプはdouble であり、 のメンバーにはdouble はないので、bbによって2つの に けられる: 1の はa、bbの2つの があり、aの さは1であり、bbの さは24であり、8の25より きい 32をとる. 2の はccがあり、 さは4であり、 8の4より きい は8である.2つの の は40であるためsizeof(test 3)=40である.
(4)
struct test4 
{ 
 char a; 
 int b; 
}; 
struct test5 
{ char c; 
 test4 d; 
 double e; 
 bool f; 
};

sizeof(test 5)の を めます:test 5は らかに test 4を んで、 2によってsizeof(test 4)=8を りやすくて、しかもそのメンバーの の さは4です; test 5の メンバー は8(double )、 である. きなヒントeは であり、test 5は2つの に かれている. 1の はc、d、eからなり、 さは1、8、8であるため、 は17であり、8の17より きい は24である. 2の はfからなり、 さは1であり、8の1より きい は8であり、2つの と32であるため、sizeof(test 5)=24+8=32である.
 
、union
Unionの さは、その さが も きいメンバー の さに します.すなわちunionではメンバー が して され,その アドレスは じである.
はunion( )の メンバーは じアドレスで を し、 に1 のメンバーしか できないので、メモリユニットを り てる に2 :1を たす がある. に、 タイプは、 も いメンバーが める を に する.     2.この の が のメンバーのメタクラス ( であればそのタイプのデータ を り、 int a[5]は4)に して を たさない 、この は に びる.このコードを てみましょう.
  union   mm{    
  char   a;//   1    
  int   b[5];//   4    
  double   c;//   8    
  int   d[3];    
  };   

mmの はsizeof(int)*5=20であるべきである.しかし、20 のユニットだけなら、いくつのdouble (8ビット)を できますか? つ ?もちろんできないので、mmの は20より きく、 のメンバーが とする の を たすように びています.つまり、24です.unionの は、メンバーの でどの が きいかを て、 のメンバーの の さと して、 できればいいです.
 

#pragma pack()コマンド
コンパイラのデフォルトの わせ を するにはどうすればいいですか?1.VC IDEでは、[Project]|[Settings],c/c++タブCategoryのCode GenerationオプションのStruct Member Alignmentで できます.デフォルトは8バイトです.2. には、#pragma packのように に することができる. :progmaではなくpragmaです.
に、 #pragma pack(n)を すると、コンパイラはnバイトで する. #pragma pack()を して、カスタムバイト わせを します.
:pragma pack(n)で したnが の メンバーsizeより きい 、 は せず、sizeの メンバーに って を わせます.
スペースを するために、 に#pragma pack()コマンドでプログラムの を することができ、カッコ は のバイト であり、このコマンドのカッコ の が であればデフォルトの である.たとえば、 の の の 、このコマンドで バイト を で すると、 のようになります.
#pragma pack(2)//2バイトの わせを
struct strdent  
{  
    char name[5]; //  1    , 2     , 1      
    int num;          //  4    , 2     , 2      
    short score;    //   2    ,   2      
} 

#pragma pack()/ のpack を し、 をキャンセルしたバイト わせ
するとnumは6バイト (オフセット )から され、scoreは10バイト (オフセット )から されるのでsizeof(student)=12となり、そのデータは の に する.
|char|char|  
|char|char|  
|char|----| 
|----int--| 
|----int--| 
|--short--| 

このようにデフォルトのバイト を することで、 をより に することができるが、これはコンピュータのデータの み き を させ、 で を り える である.