ショートカット
ファシリテーター × あり方
コーディングの向こう側
Hello, ANOTHER world!
オブジェクト指向のはなし
プログラミングのはなし
C言語実力診断クイズ
eSkillBooks
Hello, ANOTHER world!

メモリの中を想像する - その1

コンピューターが扱う情報は、どんなものであれビットの集まりで表現されています。メモリはコンピューターで扱う情報を格納する場所ですから、ビットの集合体です。1ビットの値を格納できる記憶装置が、ひたすらずらーっと並んでいるようなものです。それはちょうど次のようなイメージです。
しかしこのままでは不便ですね。1ビットで表現できる値はたったの2通りですから、ちょっとした足し算をするだけでも大変なことになってしまいます。そこで、ビットを8つ毎にひとまとめにしたものがバイトです。そうすると、メモリはバイトがずらーっと並んだ状態になります。バイトは8ビットですから、2の8乗通り(256通り)の値を表現できることになります。
さて、バイトにアクセスするためには1つ1つのバイトを区別しなければなりません。そこで、全部のバイトには固有の番号が割り当てられています。最初のバイトが0、次が1、その次が2という風に順番に割り当てられています。これがアドレスです。アドレスによって、メモリ上のあらゆるデータにアクセスすることが可能になります。アドレスは(ビットではなく)バイトに割り当てられているため、メモリ上でアドレスによって区別できるデータの最小単位はバイトになります。ビットにアクセスするには、あらかじめそのビットが含まれるバイトをアドレスによって取り出し、さらにバイト中でのビット位置を指定してビットを取り出します(そのためにビット演算子の & や | があります)。
通常、char 型がバイトに相当します。signed char が -128〜127、unsigned char が 0〜255 の範囲の数値を表せることを思い出してください(どちらも256通りですね)。
もっともたくさん使われるのは int 型でしょう。int 型は char 型よりもずっとたくさんの値を表現できます。これは、ビットを組み合わせてバイトにしたのと同じように、バイトを組み合わせることによって実現されています。多くの環境では int 型は4バイト(本当に4バイトかどうかは sizeof(int) の値を調べればわかります)ですから、メモリ上では次のような感じになります。
左の図では int 型の値が隣接して描かれていますが、このように同じ型の値が連続的に格納されるのは配列変数の場合です。文字列では char 型の値が連続していることを思い出してください。
では、ポインタはどうなっているのでしょう?よく「ポインタは難しい」と言われますが、そんなことはありません。ポインタは、一言で言うと、アドレスを格納するための変数です。int 型の変数 n と、その n を指し示すポインタ p を考えてみましょう。
ほら、図にしたらとっても簡単でしょう?メモリ上に変数 n の実体があって、そこに n の値(ここでは 123)が格納されています。n のアドレスは a です。ポインタも変数の一種ですから、p の実体も n と同様にメモリ上にあって、そこには n のアドレス a が格納されています。ポインタを経由して別の変数にアクセスできるのは、こういう仕組みによるのです。
ポインタがメモリ上にあるということは、ポインタにもアドレスがあります。そこで、ポインタを指し示すポインタというのも作ることができます。今度は int 型の変数 n を指すポインタ p を指すポインタ pp を考えてみましょう。ややこしい?では図にしてみましょう。
pp には p のアドレスである b が格納されます。簡単な仕組みでしょう?
「ポインタは難しい」と感じるかどうかは、単にメモリの中身が想像できるかどうかにかかっているということがわかっていただけたでしょうか?
さて、ここまでわかれば argv のイメージを完全につかむことができます。argv は文字列へのポインタの配列です。そして文字列は char 型の配列です。ですから次のようになっています。
スルドイ方ならもうお気づきでしょうが、どんなデータでもメモリ上に格納される以上は格納するための領域とそのアドレスがあります。ポインタも構造体も、どんな型の値でも同じことです。そして、驚くべきことに、プログラム自体もそうなっています。それについてはまた次回にお話しします。

("Hello, ANOTHER world!" は2001年11月から2002年11月にかけて作成されたコンテンツです。)