Phase #09

ポインタ


1.変数のアドレスとポインタの関係

今までにさまざまな型の変数を学習してきました。変数というのはデータを記憶しておく箱のようなもの、ということは十分理解できたと思います。このデータを記憶しておく箱にあたるものはコンピュータの中では、メモリと呼ばれる部分になります。
メモリはデータを記憶しておく箱の巨大な連なりです。この箱一つ一つを特定するために、最初から順番に通し番号がつけられています。これがメモリアドレス(単にアドレスと呼ぶことが多い)というもので、まさに「メモリの場所を表す番地」なのです。
今までみてきたことの中ではこのメモリアドレスを意識することは特にありませんでした。そこで、このメモリアドレスを意識して今までやったことを改めて見てみましょう。

メモリ上の様子例えば、char型の変数 moji を宣言したとします。プログラムでは次のようになりますね。

 char moji;

このプログラム文の実行時にはまずメモリ中の使われていないアドレスを探し出します。そして、そのアドレスを変数 moji のために割り当てるのです。仮に、1000番地が空いていたとします。
次に、変数 moji に'A'を代入すると、メモリの1000番地の内容が'A'になるわけです。つまり言い換えれば変数 moji に値を代入するということは、実際にはメモリの1000番地の値を書き換えている、といわけです。この「1000番地に値を代入する」的な考え方でプログラムする時に使うのが今回学習するポインタなのです。
実際にはポインタは何を表すのでしょう?一言で言ってしまえば「データのアドレスを記憶する変数」、それがポインタなのです。上の例で変数 moji のアドレスを記憶するポインタを宣言すれば、そのポインタの内容は「1000」になっているわけです。一見するとあんまり意味のなさそうなポインタ、実はとても便利でこれによって実現できることは飛躍的に増えるのです。その分多少理解しにくい面もありますが、基本の「ポインタはアドレスを記憶している」ことを常に頭においておけば必ず理解できます。それではゆっくりと進んでいきましょう。

2.ポインタの宣言


ポインタも普通の変数と同じで宣言をしないといけません。仕方も変数の場合に似ていますが、識別子の前に「*」をつけなければいけません。

 データ型 *識別子 

変数と一度に宣言することもできます。

char a, b, *p;

また次のように記述してもポインタと判断されます。

char* p;

しかし、複数のポインタを宣言するときにはこの方法で記述しないほうが良いです。例えば、ポインタ p, q, r を宣言するのに、

char* p, q, r;

としても、実際にはコンパイラには

char *p, *q, *r;

ではなく、

char *p, q, r;

と判断されてしまい、q と r がポインタとみなされず普通のchar型変数になってしまうからです。

3.ポインタの使い方


ポインタには特別の演算子があります。この演算子を使うことでポインタを効率的に扱えます。

演算子記述例演算子の働き
&&data変数のアドレスを示す
**dataそのポインタの記憶しているアドレス上にある値を返す

それではこれらの演算子の使い方、働きも含めてポインタを操作する度にどのように変化していくのかを見ていきましょう。

1.ポインタの宣言
ポインタは宣言したときはどのアドレスを指し示しているかは不明です。

 int data1, data2, *pdat; /* 変数・ポインタの宣言 */
 data1 = 20; /* 変数の初期化 */
 data2 = 135;

変数data1, data2 が宣言されるとメモリの空いている領域がそれぞれに割り当てられます。data1が1000番地、data2が1002番地に割り当てられたとします。次に 20, 135 が代入されるとメモリの相当するアドレス部分の値が書きかわります。しかし、ポインタの pdat は宣言されただけではどのアドレスを示すかは不明です。
ポインタを宣言

2.ポインタへのアドレス代入
変数のアドレスをポインタに代入するときに演算子「&」を使います。変数 data1 のアドレスをポインタ pdat に代入したいときは次のようにします。

 pdat = &data1; /* data1 のアドレスをポインタに代入 */

この文を実行すると、pdatの値は data1 のアドレスである1000 になります。
ポインタにアドレスを代入

3.ポインタによる値の参照
ポインタの前に演算子「*」を付けるとそのポインタの指し示しているアドレスの値を参照します。上の文を実行した後は *pdat は 20 となるわけです。
この状態で data1 の値を変更すれば当然 *pdat も変わります。data1 を 14 にすれば、*pdat も 14 になります。

 data1 = 14; /* data1 に 14 を代入 */
ポインタを使って値参照

この演算子「*」を使って参照した値は今までの変数から変数への代入と同じように別の変数に値を代入することが出来ます。

 data2 = *pdat; /* ポインタ pdat の参照している値を変数 data2 に代入 */
ポインタを使って変数に値を代入

pdat は data1 を指し示しているので、これは下の代入文と同じ働きとなります。

 data2 = data1;

4.参照アドレスの値の変更
演算子「*」を使うと逆にポインタの参照しているアドレスの値を変更することもできます。

 pdat = &data2; /* data2 のアドレスをポインタに代入 */
 *pdat = 50; /* ポインタ pdat の参照しているアドレス上の値を変更する */
ポインタの参照しているアドレスに値を代入

pdat は data2 を指し示しているので、これはつまり下の文と同じ働きをします。

 data2 = 50;

以上がポインタの最も基本的な使い方です。しっかりと把握できたでしょうか?
まだ基本段階なので実用的とはいえない使い方ですが、これを応用すると便利な使い方もできるのです。いずれにしてもこの部分は大切なので、しっかりマスターしてから次の段階に進むようにして下さいね。

 [ 例 ] ポインタの基本的な使い方  ex9-1.cGet! ソースファイル


Jump to Phase #08-2Phase #08-2: 変数の記憶クラス(2) へ
Phase #09-2: ポインタ(2) へJump to Phase #09-2

△戻る
▲トップに戻る