C言語のメモリアライメントの問題

メモリアライメントの理由

メモリの最小単位はバイトであり、CPUはメモリからデータをブロック単位で読み取り、ブロックサイズは2のn乗です。

メモリアライメントは、メモリアクセスを改善するためのオペレーティングシステムの戦略です。メモリにアクセスするときは、毎回特定の長さが読み取られます(この長さは、オペレーティングシステムのデフォルトのアライメント番号、またはデフォルトのアライメント番号の整数倍です)。アクセスするためにアライメントなし変数に2回アクセスできます。

上の図のように、各単位は1バイトで、charは1バイトを占めます。以下にint型のデータを配置する場合、どこに配置する必要がありますか?

アドレス1からアドレス4に配置する場合、この場合、4バイトのブロックサイズを追加します。このデータを取り出すには、最初のブロックと2番目のブロックを取り出す必要があります。最初のブロックの最後の3バイトを取り出します。最初のバイトはスプライスされます。もう一度メモリにアクセスする必要があります。

アドレス4の先頭にintデータを配置します。時間と空間のトレードオフのアイデア。

アライメントを記憶する方法は?

標準のデータ型の場合、そのアドレスはその長さの整数倍である必要があります。

構造などの非標準のデータ型の場合、次の配置原則に従う必要があります。

1.配列メンバーの配置規則。最初の配列メンバーはオフセットが0の場所に配置し、将来の各配列メンバーはオフセットがminの整数倍(現在のメンバーのサイズ、#pargamaパック)の場所に配置する必要があります。 (n))(たとえば、intは32ビットマシンの#pargama pack(2)では4バイトであり、2の倍数で格納を開始します)

2. sizeofの結果である構造体の合計サイズは、minの整数倍(構造体の最大メンバー#pargama pack(n))である必要があります。これは、整列するには不十分です。

3.構造体はメンバーの配置規則です。構造体Bが別の構造体Aにネストされている場合でも、最大のメンバータイプのサイズに合わせて配置されますが、構造体Aの開始点は最大のメンバーの整数倍です。 Aで。(構造体Bには構造体Aがあり、Aにはchar、int、doubleなどのメンバーがあります。AはBの整数倍から格納する必要があります。)構造体Aのメンバーの配置規則は依然として原則1を満たしています。原則2。

#include<stdio.h>
#include<stddef.h>
#pragma pack(show)  //查看对齐模数,默认为8
//#pragma pack(1)

//对于自定义数据类型,内存对齐规则如下;
//1.从第一个属性开始,偏移为0
//2.第二个属性开始,地址要放在  该类型整数倍  与  对齐模数比   取小的值  的整数倍上
//3.所有的属性都计算结束后,整体再做二次对齐,整体需要放在属性中 最大类型 与 对齐模数比 取小的值 的整数倍上
typedef struct _STUDENT{

	int a;    //0~3
	char b;   //4~7
	double c; //8~15 
	float d;  //16~19
}Student;

void test01()
{
	printf("size of = %d\n",sizeof(Student));
}



int main()
{
	test01();
	
	return 0;
}

サイズ= 24
続行するには任意のキーを押してください...

まず第一に、なぜそれは24ですか?アライメント係数比とは何ですか?

コードに#pragmapack(show)を追加してから、コードを再実行する必要はありません。コードを再生成するだけで、アライメント係数比を確認できます。

デフォルトのアライメント係数比は8であることがわかります。ルールによれば、3番目の記事によると、全体をmin {8,8} = 8の整数倍に配置する必要があります。20はそうではないため、24になります。

アライメント係数は変更できます。たとえば、2のn乗に変更できます。

#pragma pack(1)に変更すると、実行結果は17と表示されます。このようにすると、アライメントがまったくなくなり、データがすべて愛されます。  

構造がネストされている場合:

#include<stdio.h>
#include<stddef.h>
#pragma pack(show)

//对于自定义数据类型,内存对齐规则如下;
//1.从第一个属性开始,偏移为0
//2.第二个属性开始,地址要放在  该类型整数倍  与  对齐模数比   取小的值  的整数倍上
//3.所有的属性都计算结束后,整体再做二次对齐,整体需要放在属性中 最大类型 与 对齐模数比 取小的值 的整数倍上
typedef struct _STUDENT{

	int a;    //0~3
	char b;   //4~7
	double c; //8~15 
	float d;  //16~19
}Student;

//结构体嵌套结构体时,首先Student b 放在 Student中最大数据类型的整数倍上就可以,所以8,它的size为24,所以0~7,8~31,32~39
//然后二次对齐,这时候他不是看Student类型最大size,而是看Student中最大类型,为8,所以40是8的倍数,不用再对齐
typedef struct _STUDENT2{

	int a;    //0~7
	Student b;   //8~31
	double c; //32~39 
}Student2;

void test01()
{
	printf("size of = %d\n",sizeof(Student));
}
void test02()
{
	printf("size of = %d\n",sizeof(Student2));
}



int main()
{
	test01();
	test02();
	return 0;
}

演算結果:

サイズ= 24
サイズ= 40
続行するには任意のキーを押してください...

 

 

おすすめ

転載: blog.csdn.net/weixin_42596333/article/details/104510460