前回の問題を解決する前に、ポインタ変数、アドレス渡しについて説明します。
「ポインタ変数」とは、メモリアドレスを入れるための特殊な変数です。
変数宣言は、
int *p;
のように、変数名の前に「*」を付けます。
この「ポインタ変数」にはメモリアドレスが入りますから、他の変数を用意して試してみましょう。
※コラム「メモリアドレスについて」は確認しておいてください。
ある変数のアドレスを使いたい場合、変数名の前に「&」を付ければ良かったですよね。
変数valueを宣言し、そのアドレスを確認します。
<sample program 133-01>
#include <stdio.h> int main(void) { int value; printf("value address = %p\n", &value); return 0; } |
<実行結果>
value address = 0061F958 続行するには何かキーを押してください・・・
※実行結果は毎回変わる可能性があります。
このアドレスを入れる変数が「ポインタ変数」です。
ポインタ変数pを用意し、変数valueのアドレスを入れてみましょう。
<sample program 133-02>
#include <stdio.h> int main(void) { int value; int *p; p = &value; printf("value address = %p\n", &value); printf("p = %p\n", p); return 0; } |
<実行結果>
value address = 00D0FAEC p = 00D0FAEC 続行するには何かキーを押してください・・・
※実行結果は毎回変わる可能性があります。
きちんと変数valueのアドレスが入っています。
しかし、アドレスを入れることで何のメリットがあるのか・・・
これが分からないと使い道が分かりませんね。
段階を追って説明します。
まずは変数valueに値を代入し、表示するプログラムを追加してみます。
<sample program 133-03>
#include <stdio.h> int main(void) { int value; int *p; value = 123; p = &value; printf("value address = %p\n", &value); printf("p = %p\n", p); printf("value = %d\n", value); return 0; } |
<実行結果>
value address = 001EF920 p = 001EF920 value = 123 続行するには何かキーを押してください・・・
※実行結果(アドレス部分)は毎回変わる可能性があります。
普通に変数valueの中身が表示されました。
ポインタ変数pには変数valueのアドレスが入っていますので、ポインタ変数pから間接的に変数valueの中身にアクセス可能です。
<sample program 133-04>
#include <stdio.h> int main(void) { int value; int *p; value = 123; p = &value; printf("value address = %p\n", &value); printf("p = %p\n", p); printf("value = %d\n", value); printf("*p = %d\n", *p); return 0; } |
<実行結果>
value address = 002CFAA0 p = 002CFAA0 value = 123 *p = 123 続行するには何かキーを押してください・・・
※実行結果(アドレス部分)は毎回変わる可能性があります。
これがポインタの大きな役割の1つです。
仕組みを図にして説明したいので、プログラムを変更します。
<sample program 133-05>
#include <stdio.h> int main(void) { int value = 123; int *p; p = &value; printf("*p = %d\n", *p); return 0; } |
<実行結果>
*p = 123 続行するには何かキーを押してください・・・
int value = 123; |
この時点で、パソコンのメモリ上に変数valueの領域が確保され、初期値123がセットされます。
(アドレスは適当です)
メモリ +--------+ 002CFA9C番地 | | +--------+ 002CFAA0番地 | 123 | ← 変数value +--------+ 002CFAA4番地 | | +--------+
int *p; |
次に別のメモリ上にポインタ変数pの領域が確保されます。
(変数pのアドレスは今回は重要では無いので書きません)
+--------------+ | | ← ポインタ変数p +--------------+
p = &value; |
この1行で変数valueのアドレスがポインタ変数pに入ります。
+--------------+ | 002CFAA0 | ← ポインタ変数p +--------------+
メモリアドレスというものはプログラムが異なっていても重複することはありません。
皆さんが使っているパソコンで「002CFAA0」というアドレスは1つしか無いのです。
この状態で、プログラム中に
*p |
と書くと「ポインタ変数pに入っているアドレスの中身」を指すことになります。
ポインタ変数pには「002CFAA0」というアドレスが入っていますから、その中身は「123」になります。
変数valueのアドレスを受け取ることで、valueという名前を使わず、ポインタ変数pから間接的に変数valueの中身にアクセスすることが可能になります。
これを関数の引数として使うことで、今まで出来なかったことが出来るようになります。
次回は、関数の引数としてのポインタ変数について説明します。