ポインタとメモリ その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;
- aに0x2000番地、bに0x2001番地が割り当てられます。 割り当てられただけでまだ中身は不定です。
0x2000 | xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
- a、つまり0x2000に10(0x0A)という値が格納されます。 bは確保されてはいますが、まだ値は不定です。
0x2000 | 0A xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
- 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にコピーされるということです。
当たり前に感じるかもしれませんが、実体が同じなのか異なるのかはポインタを考える上で大変重要です。
ということで、実体についての例として、次回は値渡しと参照渡しについて見ていきたいと思います。
こんな感じで書いていこうと思います。今回はどう書くか悩みすぎた…。次からはもっと短いスパンで書いていきたいです。
なれていかねば。
間違いの指摘やなにか質問ありましたらコメントいただけると嬉しいです。
C言語入門の前に
プログラミング入門というと、最近だとpythonかjavascriptが多いんですかね。
アプリとかもあるからSwift, java, C#らへんもはじめに扱うことが多そうですね。
でも組み込みのプログラミング入門と言ったらやはりC言語だと思うのです。
(もしかしたらアセンブラという方もいるかもしれませんが…)
ところが、C言語と聞くと魔の”ポインタ”の存在があります。
私もポインタの概念を理解するのにはなかなか時間がかかりました。
皆、中身は簡単だから理解できればすぐだよ、と言います。
なんで理解しにくいんだろう。。
私は、”メモリ”の概念がちゃんと掴めてないからポインタが理解できないのだと考えています。
逆に言えば、メモリの概念がつかめれば、ポインタはすぐ理解できると考えています。
いや、そもそも組み込みシステムの話から入るべきですね。パソコンと共通のところも多いですが。
組み込みシステムの話をする上で、ハードウエアの話無しで進めるのは無理ってもんです。
というわけで、次回は組み込みシステムのハードウエアのお話に入っていきたいと思います。
私とプログラミングの出会い
とりあえず、当面は組み込みプログラマになった経緯から入って、当時の自分が欲しかった情報を入れつつ、プログラミングについて書いていければと思います。
きっと当時の私と同じようなことを考えている方もいるかと思いますので…。
私がパソコンを触ったのは小学生の頃、親が仕事で使っていたWindows 3.1が初めてでした。当時はプリインストールされているゲームで遊ぶ程度でしたが、Yahoo!チャットとともに小学生高学年を過ごし(携帯持ってないので家で同級生とチャットしてました)、気づくとパソコンというものはどういう仕組みなのかが気になっていました。
小学生のクラブではコンピュータクラブなるものに入り、タイピングを覚えたりましましたが、パソコンの仕組みやプログラミングというところまでは扱っておらず、 また親は両方とも理系ではなく、パソコンに疎い。近くにパソコンをよく知る大人もいなかったため、出来ることはせいぜいパソコンで調べるくらいでした。
(今なら図書館に行く、とか本を買ってもらう、とかもう少し思いつきますが、当時は全然思いつかなかったのです)
どうやらパソコンはプログラムというものが動いているらしい、プログラムはC言語というもので作れるらしいことはわかったのですが、当時の私にはそのC言語がどういう風になってるのかてんでわかりませんでした。
そもそもプログラムがどこから始まるのかすらわからなかったのです。
中身はよくわからないが、書かれている通りにテキストをコピーして、コンパイルして実行すると、たしかに”hello world!”と表示されました。
で?
これが一体どうなればWindowsで実行されるゲームになるというのか。
C言語入門を進めていっても一向に画像を表示する気配はない。ここで知った内容をどう活かしたらゲームが作れるのだろう。。わからん。
そんな感じでした。
というわけで、次から当時の自分でも納得できるように、パソコンの仕組みからプログラミングの話をしていきたいと思います。
(やっと本題に入れる)