ポインタは、C言語で最も難しいテーマの一つです。
しかし、ポインタを理解すると、配列、関数、構造体、メモリ管理など、より高度なC言語の世界へ進むことができます。
今回は、ポインタとは何か、ポインタを使う上で最低限必要なことに絞って解説します。
アドレスの仕組み
ポインタを学ぶ前に、アドレスの仕組みについて少し触れておきます。
変数の値は、コンピュータのメモリに記憶されています。
このメモリは、たくさんの小さな箱(1バイトごと)が並んでいて、それぞれの箱には「アドレス」と呼ばれる番号が付いています。
変数の値が格納されているメモリをアドレスを知るには、アドレス演算子である & を使います。
&変数名次に実際にプログラムして、変数のアドレスを確認してみましょう。
#include <stdio.h>
int main(void)
{
int num = 5;
printf("変数numの値は、%dです。\n", num);
printf("変数numのアドレスは、%pです。\n", &num);
return 0;
}実行結果は次の通りです。
変数numの値は、5です。
変数numのアドレスは、00000006498FFC4Cです。プログラムの7行目のprintf関数は、これまでどおり、変数numの値である 5 が出力されます。
次の printf 関数では、アドレス演算子を使た「&num」を出力しています。これで、変数numのアドレスを出力することができます。
また、アドレスを出力するには、 %p の書式指定子を使います。&num の値を見ると、6498FFC4Cと16進数で出力されていることがわかります。これがメモリのアドレスになります。
このメモリのアドレスは、環境によりことなりますので、皆さんが実際にプログラムを実行した結果は別の値になっていると思います。
ポインタとは
先ほど、変数のアドレスを確認しましたが、今度は、このアドレスを扱うために、必要なポインタについて説明します。
ポインタとは、変数が入っている“メモリ上のアドレス”を覚えておくための変数です。
この変数の定義は、次の構文になります。
型名 *変数名;このように、ポインタの変数を使用するには、必ず * という記号を付けます。
次に、ポインタにアドレスを格納するプログラムを見てみましょう。
#include <stdio.h>
int main(void)
{
int n = 5;
int *pNum;
pNum = &n;
printf("変数nの値は、%dです。\n", n);
printf("変数nのアドレスは、%pです。\n", &n);
printf("ポインタpNumの値は、%pです。\n", pNum);
return 0;
}実行結果は次の通りです。
変数nの値は、5です。
変数nのアドレスは、00000024EAD2F80Cです。
ポインタpNumの値は、00000024EAD2F80Cです。プログラムの8行目で、変数nのアドレスをポインタ変数pNumに代入しているため、ポインタ変数pNumは変数nのアドレスと同じになります。
ポインタ変数値のアドレスから値を取得する
ポインタ変数には、アドレスが格納されています。
このポインタ変数が示しているアドレスに格納されている値を知りたい場合は、次の構文を用います。
*ポインタ変数;このように記述すると、そのポインタ変数に格納されているアドレスに対応する変数の値を知ることができます。
では、次のプログラムで確かめてみましょう。
#include <stdio.h>
int main(void)
{
int n = 5;
int *pNum;
pNum = &n;
printf("変数nの値は、%dです。\n", n);
printf("変数nのアドレスは、%pです。\n", &n);
printf("ポインタpNumの値は、%pです。\n", pNum);
printf("*pNumの値は、%dです。\n", *pNum);
return 0;
}実行結果は次の通りです。
変数nの値は、5です。
変数nのアドレスは、0000001DC3CFFADCです。
ポインタpNumの値は、0000001DC3CFFADCです。
*pNumの値は、5です。プログラムの13行目で、*pNum の値を出力すると、変数 n の値になっていることがわかります。
まとめ
- ポインタは「アドレス」を覚える変数
&変数名は「その変数のアドレス」*ポインタは「ポインタの指すアドレスにある値」- ポインタ自身も変数なので「アドレス」をもつ
- 宣言の
*と、値取得の*は意味が違う - 初級編ではこの3点だけ覚えれば十分
- ポインタ = アドレス
&= アドレスを取る*= アドレスへ行って値を見る