メモリ位置合わせ


このブログのテーマを見て、どんなテーマがどういう意味なのか考えるかもしれません.まず、あなたが空間を申請する時、システムはあなたが申請した空間の大きさに基づいて、一定の規則に従って、彼に空間の開始住所を割り当てて、それからあなたは安心してあなたのデータを書くことができます.今日、このブログでは、システムがどのようなルールに従って空間を割り当てているのかについて話します.正式に始まる前に、私たちはまず牛刀を試します:struct t t 1{char a;short b;int c;};すみません:sizeof(struct t 1)の値はいくらですか?struct t2 {char a;int b;short c; }; sizeof(struct t t 2)はいくらですか?答えはここで先に明らかにして、私たちはまず後ろの内容を見てみましょう.1.まず、メモリの位置合わせというメカニズムを説明します.私たちに普及すべきは、C言語は効率を非常に重視する言語です.今日、メモリがますます大きくなると、スペースの代わりにプログラムを効率的に実行することができます.これがメモリの位置合わせの原因だと思います.まず例から始めましょう.アドレスが0 x 00000001であるとしたら、次の4バイトからint型データを取ります.それは最速の速度でしかできません.まず1バイトのchar(0 x 0000001)を取り、それから2バイトのshort(0 x 0000002-0 x 0000003)を取ってからchar(0 x 0000004)を取り、int値を読むことができます.では、仮に、0 x 0000004から値を読み始めたとしましょう.直接4バイトのintで間もなく十分です.この効率比は3対1だ.2.さて、上記の内容を見て、システムがどのように位置合わせされているかを考え始めるかもしれません.基本データ型では、メモリの最初のアドレスが彼の長さの整数であればよいが、非基本型では、配列:最初の要素が位置合わせされ、後ろの要素が自然に位置合わせされる.連合体:エレメントの最長値を整列値とします.構造体:各データ型は位置合わせが必要で、具体的な方法は以下の通りです:この問題を話す前にまたいくつかの小名詞を補充します:a.位置合わせ値:つまりデータの実際のアドレスはDで、D%N==0で、Nは彼の位置合わせ値です.b.データ型の自己整列値:charの自己整列値は1、shortは2、int float doubleは4である.c.構造体と連合体の自己整列値:彼の整列値はデータ構造の中で、データ型の自己整列値が最大の値である.d.位置合わせ値の指定:位置合わせ値がvcの下で#pragrapack(n)であることを指定します.ここで、nはいわゆる指定位置合わせ値です(gcc、vcのデフォルト位置合わせ値は4).e.データメンバーまたは構造体の有効な整列値:指定された整列値と自己整列値のうちの1つです.f.有効整列値丸め:構造体が占有する総長さがその有効整列値の整数倍でなければならない.次に例を挙げると、struct A{int a;short b;};仮にaが0 x 00000000に割り当てられているとすると、int自体の位置合わせ値は4であり、デフォルトの指定位置合わせも4であるため、aがここから4バイト割り当てを開始するとすると、int次の要素理論の開始アドレスは0 x 0000004であり、shortがここから割り当てることができるかどうかは、その有効位置合わせ値を見る必要がある.彼の有効な位置合わせ値は2で、0 x 000000004は明らかに2の整数倍なので、shortは0 x 000000004-0 x 000000005を占めています.もしかして、sizeof(struct A)は6?いいえ、彼の有効な位置合わせ値に基づいて丸くする必要があります.すなわち、(4+2+2)%4==0です.これが有効な整列値の丸みです.そういえば、ブログの前の2つの例題に答えがありましたね.t 2を分析してみましょう.まず、システムがcharに割り当てた空間開始アドレスが0 x 00000000であると仮定します.charの有効位置合わせ値は1であるため、次の要素はもともと0 x 000001からですが、次の要素はintであるため、彼の有効位置合わせ値は4で、システムはcharの後に3つの空のバイトを補充し、intは0 x 00000000から割り当てられます.int次の要素の開始アドレスは0 x 0000008であり、彼はshortの有効な位置合わせ値の整数倍であるため、shortは彼から割り当てられ、彼は0 x 0000008-0 x 0000009を占有する.また、有効な整列値の丸みの関係、shortの後に2バイトを揃えるのでsizeof(struct 1)は12である.同理sizeof(struct t 1)は8である.これにより、変数値の順序を合理的に定義することで、メモリ領域を節約できることがわかります.そういえば、0 x 00000000から0 x 00000000への割り当てを仮定して、0 x 00000001から割り当てると、sizeof(struct t 1)の可能な値が異なるのではないでしょうか.実は、これを聞くと、私はまだ説明できません.関連資料も見つかりません.自分で実験したものしか言えません.もしあなたの構造体要素の長さが最も長いのがcharまたはshortであれば、最初の要素の開始アドレスは必ずD%4==2である.最長intであれば、アドレスD%4==0;floatまたはdoubleの場合、構造体の開始アドレスD%8==0.(もちろん、32ビットマシン、gccのコンパイル環境を使っています).ここで、位置合わせ値がデータ型自体のプロパティであることに対して、指定した位置合わせ値を変更できるという問題があると思います.それは#pragma pack(n);nの値.例:
#pragma pack(1)
struct t2
{
	char a;
	int b;
	short c;
};
#pragma pack()
int main(void)
{
	printf("%d
",sizeof(struct t2)); return 0; }

では、出力値は7です.3.位置合わせを設定できる場所.異なるCPU下での通信プロトコルを設計する場合や,ハードウェアドライバを記述する際のレジスタの構造の両方を1バイト単位で整列させる必要がある.もともと自然に整列しているように見えても、コンパイラによって生成されるコードが異なるように整列させます.
さて、これについて言えば、私はもうロバの技術が貧乏ですが、資料を探している間にintelとマイクロソフトと呼ばれる筆記試験のテーマを見て、みんなと分かち合いました.
#pragma pack(8)
struct s1
{
	short a;
	long b;
};

struct s2
{
	char c;
	struct s1 d;
	long long e;
};
#pragma pack()

問1.sizeof(s2) = ?2.s 2のcの後ろに何バイト空いてd?
理論的には24ですが、gccは20(まだ考えていないかもしれませんが、アドバイスをお願いします)ですが、vcでは24です.
なぜだろう.もとは、gccの最大pragmaは4なので、あなたは知っています.sizeof(s 2)は20になった.よし、文章はこれで終わりだ.私のブログに何か意見や見方があれば、伝言を歓迎します.
推薦ブログ:http://blog.csdn.net/21aspnet/article/details/6729724(詳しく話しています).