c++におけるsizeof演算子による構造体サイズ計算問題の検討

3022 ワード

c++で提供されるsizeof演算子は、sizeof(int)、sizeof(char)、sizeof(double)の戻り値がそれぞれ4,1,8のような内蔵タイプのバイト数サイズを計算するのに便利であることは理解しやすい.しかしsizeof演算子を構造体変数の計算に使用するメモリが大きい場合、予想外の場合があります.
たとえば、ここでは構造体を次のように定義します.
1   typedef struct
2
3     {
4
5       int a;
6
7       char b;
8
9     }struct1;

 
常識的に計算すると,intタイプの変数は4バイト,charタイプの変数は1バイトであり,1つのstruct 1タイプの変数は必ず5バイトであり,2つのメンバーの加算であるが,プログラムで実験した結果,実際にsizeof(struct 1)の値は8であり,疑わしいことが分かった.
実際,構造体がコンパイラによってコンパイルされる場合,その占有するメモリ空間の大きさはコンパイラによって決定され,コンパイラのプリコンパイル命令を用いてこのデフォルト値を得ることができる.VS 2008に#pragma pack(show)を追加すると、エンジニアリングファイルをコンパイルするときに次のような注意が表示されます.
warning C 4810:雑注pack(show)の値==8.
これが、コンパイラのデフォルトの構造体をコンパイルするときのデータ・メンバーの位置合わせです.整列は、構造体をコンパイルするときにデータ・メンバーに割り当てられるメモリ・スペースのサイズとして理解できます.この割り当てられた8バイトのメモリが切れた場合、構造体のデータ・メンバーの位置を指定し続けるために、8バイトの空間を追加します.例えば上段コードでは、まずOSが8バイトのメモリ空間を構造体に割り当て、まずint aというデータメンバーを入れ、int型は4バイトであるが、この場合4バイトが残っているので、charタイプのchar bを入れるのに十分であるため、この8バイトのメモリ空間に実際に値があるのは上位5バイトのみで、その後3バイトは何も入っていない.しかし、この構造体を計算する時間はやはり計算されるので、この構造体の大きさは8バイトです.
この結論の正しさを検証するために、いくつかの例を見てみましょう.
1 typedef struct
2 {
3 int a;
4 double b;
5 }struct2;

この構造体では、メモリ領域のサイズがそれぞれ4バイトと8バイトの整数型と二重精度浮動小数点型が定義されています.コンパイラのデフォルトの位置合わせは8です.まず、OSは1つの8バイトの空間を割り当て、int aは先に入れ、このとき4バイトの残りの空間しか残っておらず、double bを置くことができないので、OSはさらに1つの8バイトの空間を割り当て、double bを入れるので、得られるstruct 2タイプのバイトサイズは16である.
もう一度見てください.
1 typedef struct
2 {
3 int a;
4 char a[6];
5 double c;
6 }struct3;

この構造体にはchar a[6]があり、配列の大きさは順序格納の順序構造であり、そのバイトサイズは配列中の各メンバーの大きさに配列の長さを乗じ、ここでは6バイトである.まず6バイトのメモリ空間を割り当て、int aを先に装着し、char a[6]が6バイトであるため、残りの4バイトが装着できない場合は、char[6]を装着するために8バイトを割り当てる.残り2バイトはdouble cを入れられないので、8バイトを割り当てて詰めるので、構造体struct 3のバイトサイズは24バイトです.
転載先:https://www.cnblogs.com/hongfenglee/archive/2012/02/17/2355141.html