メモリの中身

最近、職場に新人の後輩が一人配属された。
私がC言語を教えることになったのだけど、普通にC言語教えても面白くない。
だから、プログラムを実行した時に、メモリの中身がどうなってるかを教えてあげようと思った。
まだ、どうやって教えるかは考えてない。
しかし、教える前に、私自身が”メモリの中身がどうなってるか”を知っておく必要がある。
そんなわけで、下記のコードを実行させ、実行中のメモリの中身を覗いてみた。

ソースコード

変数名がすごい抵当なのは勘弁して!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Point {
	int x;
	int y;
} POINT;

short gA = 100;
short gB = 200;

void main ()
{
	struct Point aaa[10];
	int bbb = 255;
	char *p;
	aaa[0].x = 10;
	aaa[0].y = 20;
	aaa[3].x = 10;
	aaa[3].y = 50;

	p = (char *)malloc(sizeof(char) * 128);
	strcpy(p , "はれってほれってひれんらー");

	printf("aaa   :%x\n", aaa);
	printf("aaa[0]:%x\n", &aaa[0]);
	printf("gA    :%x\n", &gA);
	printf("gB    :%x\n", &gB);
	printf("bbb   :%x:%d\n", &bbb, bbb);
	printf("p     :%x\n", p);

	scanf("%d", &bbb);

	printf("aaa   :%x\n", aaa);
	printf("aaa[0]:%x\n", &aaa[0]);
	printf("gA    :%x\n", &gA);
	printf("gB    :%x\n", &gB);
	printf("bbb   :%x:%d\n", &bbb, bbb);
	printf("p     :%x\n", p);

	free(p);

	scanf("%d", &bbb);
}
実行結果

真ん中の100は入力した数値

aaa   :12ff34
aaa[0]:12ff34
gA    :40d134
gB    :40d136
bbb   :12ff88:255
p     :902990
100
aaa   :12ff34
aaa[0]:12ff34
gA    :40d134
gB    :40d136
bbb   :12ff88:100
p     :902990
メモリ内容(スタック領域 数値入力前)
[Address]: +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F  0123456789ABCDEF
0012FF30 : 88 FF 12 00 0A 00 00 00 14 00 00 00 14 37 40 00  ・...........7@. 
0012FF40 : 00 02 00 00 00 D0 40 00 05 00 00 00 0A 00 00 00  .....ミ@......... 
0012FF50 : 32 00 00 00 67 4A 40 00 58 D7 40 00 00 00 00 00  2...gJ@.Xラ@..... 
0012FF60 : 02 00 00 00 00 02 00 00 0C D0 40 00 35 AA 40 00  .........ミ@.5ェ@. 
0012FF70 : 00 00 00 00 C4 D0 40 00 00 A0 FD 7F F8 00 41 00  ....トミ@..&#63728;.&#65533;・A. 
0012FF80 : 01 00 00 00 90 29 90 00 FF 00 00 00 B8 FF 12 00  ....・・....ク... 

12ff34から8byteつづ系80byteがaaa[10]の領域。
aaaはPOINT構造体の配列なので、前4byteがPOINT.xの領域で、後ろ4byteがPOINT.yの領域となる。
また、aaa[0]、aaa[3]以外は値を代入していないので、ゴミが入っている。

配列 変数名 内容
aaa[0] x 0A 00 00 00
y 14 00 00 00
aaa[1] x 14 37 40 00
y 00 02 00 00
aaa[2] x 00 D0 40 00
y 05 00 00 00
aaa[3] x 0A 00 00 00
y 32 00 00 00
aaa[4] x 67 4A 40 00
y 58 D7 40 00
aaa[5] x 00 00 00 00
y 02 00 00 00
aaa[6] x 00 02 00 00
y 0C D0 40 00
aaa[7] x 35 AA 40 00
y 00 00 00 00
aaa[8] x C4 D0 40 00
y 00 A0 FD 7F
aaa[9] x F8 00 41 00
y 01 00 00 00


12FF84からの4byteがポインタ変数のpの領域。
12ff88からの4byteが変数bbbの領域。

変数名 メモリ内容
p 90 29 90 00
bbb FF 00 00 00


他のメモリ内容もすべてリトルエンディアンであることに注意が必要。
例えば、ポインタ変数pの内容だが、リトルエンディアンなので実は00902990だ。
ちょうどpの内容を表示させた時の値と同じになっている。

メモリ内容(スタック領域 数値入力後)
[Address]: +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F  0123456789ABCDEF
0012FF70 : 00 00 00 00 C4 D0 40 00 00 A0 FD 7F F8 00 41 00  ....トミ@..&#63728;.&#65533;・A. 
0012FF80 : 01 00 00 00 90 29 90 00 64 00 00 00 B8 FF 12 00  ....・・d...ク... 
0012FF90 : 5E AC 40 00 02 00 00 00 04 22 90 00 F4 26 90 00  ^ャ@......"・・・ 

12FF88が数値入力前はFFだったのに対し、入力後は64になっている。入力した100がしっかり代入されていることが分かる。

メモリ内容(グローバル領域)
[Address]: +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F  0123456789ABCDEF
0040D120 : 00 00 00 00 00 40 00 90 00 00 00 00 00 00 00 00  .....@.・....... 
0040D130 : 00 00 00 00 64 00 C8 00 82 CD 82 EA 82 C1 82 C4  ....d.ネ.はれって 
0040D140 : 82 D9 82 EA 82 C1 82 C4 82 D0 82 EA 82 F1 82 E7  ほれってひれんら 
0040D150 : 81 5B 00 61 61 61 20 20 20 3A 25 78 0A 00 61 61  ー.aaa   :%x..aa 
0040D160 : 61 5B 30 5D 3A 25 78 0A 00 67 41 20 20 20 20 3A  a[0]:%x..gA    : 
0040D170 : 25 78 0A 00 67 42 20 20 20 20 3A 25 78 0A 00 62  %x..gB    :%x..b 
0040D180 : 62 62 20 20 20 3A 25 78 3A 25 64 0A 00 70 20 20  bb   :%x:%d..p   
0040D190 : 20 20 20 3A 25 78 0A 00 25 64 00 61 61 61 20 20     :%x..%d.aaa   
0040D1A0 : 20 3A 25 78 0A 00 61 61 61 5B 30 5D 3A 25 78 0A   :%x..aaa[0]:%x. 
0040D1B0 : 00 67 41 20 20 20 20 3A 25 78 0A 00 67 42 20 20  .gA    :%x..gB   
0040D1C0 : 20 20 3A 25 78 0A 00 62 62 62 20 20 20 3A 25 78    :%x..bbb   :%x 
0040D1D0 : 3A 25 64 0A 00 70 20 20 20 20 20 3A 25 78 0A 00  :%d..p     :%x.. 
0040D1E0 : 25 64 00 00 00 00 40 00 62 6F 72 6C 6E 64 6D 6D  %d....@.borlndmm 
0040D1F0 : 00 68 72 64 69 72 5F 62 2E 63 3A 20 4C 6F 61 64  .hrdir_b.c: Load 

グローバル変数として定義した値だけでなく、コード上の""でくくっている定数文字列もグローバル領域に配置されている。

メモリ内容(ヒープ領域)
[Address]: +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F  0123456789ABCDEF
00902980 : 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00  ............&#128;... 
00902990 : 82 CD 82 EA 82 C1 82 C4 82 D9 82 EA 82 C1 82 C4  はれってほれって 
009029A0 : 82 D0 82 EA 82 F1 82 E7 81 5B 00 00 00 00 00 00  ひれんらー...... 
009029B0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................