プログラム書いたり、もの作ったり。あと育児とか。

プログラム書いたり、もの作ったりすることについて書いていく予定です。あと育児とかも書くかもしれません。

ポインタとメモリ その1

はい、ずいぶん間が空いてしまいましたが、色々考えた結果ポインタとメモリの話から入ることにしました。

なお、とりあえずC言語の話としてみていただければと思います。言語によってこの辺大きく変わりますからね…。

ポインタのなにがわかりにくいのか

個人的には、そもそもよく使われる箱を使ったたとえがわかりにくくしていると思ってます。

と思ったのですが、結構みなさん同じこと思ってるみたいですね。少し調べたら似たようなことを言ってるサイトがたくさんヒットしました。

まぁ、当時を思い返してみると、ポインタが出てくるまでは、aにbを代入する、とか表世界の話してるのに、急に変数aのアドレス、とか裏世界の話みたいなの言われてもわけわかんないですよね。

それもそのはず、ポインタの話を理解するためには、まず変数宣言のときにメモリ上でどんなことが起きているのかのイメージを持つことが大事です。実際裏世界みたいなもんです。

メモリのイメージ

ではまず、メモリのイメージを持っておきましょう。

私のイメージはバイナリエディタです。

       | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
-------|-------------------------------------------------
0x2000 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x2010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x2020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x2030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x2040 | 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46
0x2050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x2060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x2070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

この図であれば、0x2040番地の値は0x30、0x204B番地の値は0x41、と言ったように、ある場所にある数値が格納されているイメージです。

変数を宣言する

では、次の動作はどんなイメージになるでしょうか。

char a = 1;

私は、メモリ上、RAM上のどこかに変数a用の領域が確保され、その中に"1"という値が保存されるイメージです。

スタックに入るのか、レジスタに入るのか、そもそもこいつはグローバルの話をしてるのか、ローカルの話をしているのか、とか細かい話はありますが、まずはメモリが確保されるイメージを持つことが大事です。

(実際にはレジスタにそのまま入る場合は場合はメモリは確保されないわけですが、そこはとりあえず置いときます)

つまり、あるアドレス(たとえば0x2000番地)から1byte分がaという変数用に確保され、そこに1という値が格納されるというイメージです。

       | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
-------|-------------------------------------------------
0x2000 | 01 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx

ちなみに、xxというところは不定(なにかしら値は入っているが、何かは決まっていない)状態と思ってください。

では、次の場合はどうでしょう。

char a, b;
a = 10;
b = a;
  1. aに0x2000番地、bに0x2001番地が割り当てられます。 割り当てられただけでまだ中身は不定です。
0x2000 | xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
  1. a、つまり0x2000に10(0x0A)という値が格納されます。 bは確保されてはいますが、まだ値は不定です。
0x2000 | 0A xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
  1. b、つまり0x2001番地にaの中身、つまり10が格納されます
0x2000 | 0A 0A xx xx xx xx xx xx xx xx xx xx xx xx xx xx

このときポイントとなるのは、aとbは最終的に同じ値が入っていますが、領域は別々にもっている(実体は別)ということです。

つまり、b=aとしたときに、bはaそのものになるのではなく、aの中身(今回は10という値)がbにコピーされるということです。

当たり前に感じるかもしれませんが、実体が同じなのか異なるのかはポインタを考える上で大変重要です。

ということで、実体についての例として、次回は値渡しと参照渡しについて見ていきたいと思います。


こんな感じで書いていこうと思います。今回はどう書くか悩みすぎた…。次からはもっと短いスパンで書いていきたいです。

なれていかねば。

間違いの指摘やなにか質問ありましたらコメントいただけると嬉しいです。