今回は《ポインタについて学ぼう》というテーマで記事をまとめます。
「ポインタ」はC言語において『鬼門』であり、多くの人が「C言語が嫌いになる」要素の一つです。しかし、ポインタはC言語において「究極奥義」といっても過言ではない要素です。気合を入れて学んでいきましょう!
尚、現在執筆中のC言語入門記事は以下の人を対象としています。
- プログラミング未経験の人
- C言語プログラミングの学習をこれから始めたい人
- C言語プログラミングの学習を始めたばかりの人
ポインタについて学ぼう
ポインタとは、簡単に言うと「変数の場所を指し示す変数」です。今回は「変数の場所」の概念から解説をしていきたいと思います。
変数とアドレス
ポインタを解説する前に変数とアドレスについて解説します。
まず、全てのコンピュータには「メモリ」と呼ばれる『データを一時的に保存する領域』が存在します。メモリは、コンピュータ上で何かしらの処理(文章や絵の表示、音楽の再生など)を実行する場合に使用されます。
そして、全ての変数はメモリ上にデータが保存され、変数の『メモリ上の場所』のことを「アドレス」と呼びます。(「メモリアドレス」と呼ばれることもある)
ポインタとは
つまり、ポインタとは「変数のアドレスを保存する変数」です。
そして、ポインタを使用することで、参照先変数(ポインタにアドレスが保存されている変数)への値の代入と取得をすることができます。
変数定義と使用方法
『ポインタ変数の変数定義』、『変数のアドレス取得』、『参照先変数への値の代入と取得』について、基本的な書式をまとめました。
ポインタ変数の変数定義
ポインタ変数の変数定義は、変数の型の後もしくは変数名の前に『*』(アスタリスク)を付与します。ちなみに、この『*』を間接演算子と呼びます。
基本的な書式は次の2パターンとなります。
変数の型* ポインタ変数名;
変数の型 *ポインタ変数名;
変数のアドレス取得
変数のアドレスは、参照先の変数の前に『&』(アンパサンド)を付与することで取得できます。ちなみに、この『&』をアクセス演算子と呼びます。
基本的には、取得した変数アドレスはポインタ変数に代入します。変数のアドレス取得およびポインタ変数への代入の書式は次のようになります。
ポインタ変数名 = &参照先の変数名;
尚、基本的にポインタ変数と参照先変数の型は同じものを指定する必要があります。
参照先変数への値の代入と取得
ポインタ変数を介して参照先変数へ値を代入したり、参照先変数の値を取得する場合はポインタ変数の前に『*』を付与します。
/* 参照先変数への値の代入 */ *ポインタ変数名 = 値; /* 参照先変数から値の取得 */ 他の変数名 = *ポインタ変数名;
サンプル実行
ここまでで学んだ情報を元にしたサンプルを用意しました。実行してみてください。
尚、アドレスを表示する場合、printf関数に『%p』を指定します。
#include <stdio.h> void main() { int num1 = 10; int num2 = 20; int* pnum; /* num1のアドレス取得 */ pnum = &num1; /* 参照先変数(num1)に値を代入 */ *pnum = num2; /* num2のアドレス取得 */ pnum = &num2; /* 参照先変数(num2)に値を代入 */ *pnum = 100; /* 各変数の値を表示 */ printf( " num1 = %d\n", num1 ); printf( " num2 = %d\n", num2 ); printf( " pnum = %p\n", pnum ); /* 参照先変数のアドレスを表示 */ printf( "*pnum = %d\n", *pnum ); /* 参照先変数の値を表示 */ }
NULLポインタ
ポインタは「変数の場所を指し示す変数(変数のアドレスを保存する変数)」であると解説しましたが、「どこも指し示さない状態」にしたい場合もあります。
その場合にはポインタ変数に代入する値として『NULL』を使用します。
ポインタ変数名 = NULL;
多くのケースでは、ポインタ変数の初期化時にNULLを代入しておき、様々な処理を行った結果、ポインタ変数にアドレスが格納されている場合のみ参照先変数への代入・取得を行います。
#include <stdio.h> void main() { int num = 10; int* pnum = NULL; /* ポインタ変数がアドレスを保存している場合のみ表示 */ if(pnum != NULL){ printf("(1) *pnum = %d\n", *pnum ); } /* numのアドレス取得 */ pnum = # /* ポインタ変数がアドレスを保存している場合のみ表示 */ if(pnum != NULL){ printf("(2) *pnum = %d\n", *pnum ); } }
1つ目のprintf関数実行時ではポインタ変数がNULLであった為、2つ目のprintf関数のみ実行されましたね。
また、C言語では、初期化や値の代入をしていない場合、その変数には不定の値が格納されます(開発環境によっては0が格納されている場合もある)。ポインタ変数の定義時は必ずNULLで初期化するようにしましょう。
次回も引き続き「ポインタ」について
今回は「ポインタ」の基礎について学んでもらいました。
次回も引き続き「ポインタ」について解説したいと思います。ポインタの基礎編②として、ポインタと配列の関係を解説します。
ご期待ください。