C++メモリアライメントまとめ
2028 ワード
まず、なぜ位置合わせするのかを話します.効率を向上させるために、コンピュータがメモリからデータを取り出すのは一定の長さです.32ビットマシンを例にとると、32ビット、すなわち4バイト(バイト当たり8ビット)ずつ取得される.バイトの位置合わせにはどのようなメリットがありますか?int型データを例にとると、メモリに格納されている位置を4バイトで揃える、つまり1つのintのデータがすべてコンピュータの1回の取数の区間内にある場合は、1回だけ取ればよい.整列していないと、あいにく、このintデータは取数の境界を越えているので、このintのデータを全部取るには2回取る必要があり、効率も低下します.
メモリの位置合わせの基本原則:
1.構造内のメンバーは、自身の長さで自己配置されます.
自身の長さ、例えばchar=1、short=2、int=4、double=8.自己整列とは、メンバーの開始位置のメモリアドレスが、そのメンバーの長さの整数倍でなければならないことを意味します.intは0,4,8のようなアドレスでしか開始できない
2.構造体の合計サイズは、構造体の有効な整列値の整数倍である
構造体の有効な整列値の決定:
1)明示的に指定されていない場合、構造体で最も長いメンバーの長さを有効な値とする
2)pragma pack(n)で指定した場合、nと構造体の中で最も長いメンバーの長さのうちの小さいものを値とする.
3)当用_attribute__ ((__packed__))長さを指定する場合は、この値に従って構造体の有効な位置合わせ値を強制します.
4)#pragma packと__にかかわらずattribute__どのように指定するかは、構造体の内部メンバーの自己整列が、それ自体の整列値に従って維持されます.
例
1、
struct AA{
char a;
int b;
char c;
}aa
sizeof(aa)=12
理由:charは1バイトを占め、任意のアドレスで開始でき、intは4バイトを占め、0、4、8...最初は、本題については、4からしか開始できませんが、1-3は空いていますが、最後のcharは1バイトを占めているので、総長は9で、第2の原則で、総長は4の整数倍でなければなりませんので、12しかありません.
2、
struct AA{
char a;
char c;
int b;
}aa
sizeof(aa)=8
理由:charは1バイト、アドレス1から、続くcharも1バイト、アドレス2からintは4バイト、合計6バイト、有効整列長はsizeof(int)=4なので8.
3、
#pragma pack(2)
struct AA{
char a;
int b;
char c;
}aa
sizeof(aa)=10(注:vs 2010で実行結果は8であり、メモリの分布を異なるコンパイラで最適化すべきか、実際に問題を解くか10ビットで結果を出すべきか)
理由:同例1では、総長は9バイトであり、構造体の有効整列長はpackで指定された2とintの4で小さい値2をとるため、総長は10である.#pragma pack(8)の場合、有効整列長は4、総長は12となる.
4、
struct AA{
char a;
int b;
char c;
}__attribute__((__8__))aa
sizeof(aa)=16
理由:同例1では、総長は9バイトであり、構造体の有効な整列長は強制的に指定された8バイトであるため、結果は16である.2に指定すると、結果は10になります.
5、16ビットの機械で、データ境界の位置合わせで構造がどれだけの空間を浪費したのか.
解:16ビットのマシンではintが2バイトを占めるため,構造体全体の総長さは4であるが,バイト整列により実際の占有長さは6,すなわち2バイトの浪費である.
参照先:http://blog.csdn.net/andy572633/article/details/7213465
メモリの位置合わせの基本原則:
1.構造内のメンバーは、自身の長さで自己配置されます.
自身の長さ、例えばchar=1、short=2、int=4、double=8.自己整列とは、メンバーの開始位置のメモリアドレスが、そのメンバーの長さの整数倍でなければならないことを意味します.intは0,4,8のようなアドレスでしか開始できない
2.構造体の合計サイズは、構造体の有効な整列値の整数倍である
構造体の有効な整列値の決定:
1)明示的に指定されていない場合、構造体で最も長いメンバーの長さを有効な値とする
2)pragma pack(n)で指定した場合、nと構造体の中で最も長いメンバーの長さのうちの小さいものを値とする.
3)当用_attribute__ ((__packed__))長さを指定する場合は、この値に従って構造体の有効な位置合わせ値を強制します.
4)#pragma packと__にかかわらずattribute__どのように指定するかは、構造体の内部メンバーの自己整列が、それ自体の整列値に従って維持されます.
例
1、
struct AA{
char a;
int b;
char c;
}aa
sizeof(aa)=12
理由:charは1バイトを占め、任意のアドレスで開始でき、intは4バイトを占め、0、4、8...最初は、本題については、4からしか開始できませんが、1-3は空いていますが、最後のcharは1バイトを占めているので、総長は9で、第2の原則で、総長は4の整数倍でなければなりませんので、12しかありません.
2、
struct AA{
char a;
char c;
int b;
}aa
sizeof(aa)=8
理由:charは1バイト、アドレス1から、続くcharも1バイト、アドレス2からintは4バイト、合計6バイト、有効整列長はsizeof(int)=4なので8.
3、
#pragma pack(2)
struct AA{
char a;
int b;
char c;
}aa
sizeof(aa)=10(注:vs 2010で実行結果は8であり、メモリの分布を異なるコンパイラで最適化すべきか、実際に問題を解くか10ビットで結果を出すべきか)
理由:同例1では、総長は9バイトであり、構造体の有効整列長はpackで指定された2とintの4で小さい値2をとるため、総長は10である.#pragma pack(8)の場合、有効整列長は4、総長は12となる.
4、
struct AA{
char a;
int b;
char c;
}__attribute__((__8__))aa
sizeof(aa)=16
理由:同例1では、総長は9バイトであり、構造体の有効な整列長は強制的に指定された8バイトであるため、結果は16である.2に指定すると、結果は10になります.
5、16ビットの機械で、データ境界の位置合わせで構造がどれだけの空間を浪費したのか.
struct
{
char a;
int b;
char c;
}
解:16ビットのマシンではintが2バイトを占めるため,構造体全体の総長さは4であるが,バイト整列により実際の占有長さは6,すなわち2バイトの浪費である.
参照先:http://blog.csdn.net/andy572633/article/details/7213465