プログラミング言語の中でも王道と言えるC言語。そのC言語において初学者が最もつまずきやすいテーマであるポインタにいて簡単に解説していきます。
ポインタとは
まず、ポインタを一言で表すと「メモリ上で、ある変数が格納されている領域の先頭アドレスを格納する変数」となります。
変数は2種類存在します。一つは数(1, 200など)や文字(’A’, ‘X’)などの「プログラムに直接記述できる値」を格納するもの、そしてもう一つは上記の通り、変数のアドレスを格納するものです。この記事では分かりやすいように前者を「変数」、後者を「ポインタ変数」と呼びます。
ポインタの宣言と値の代入
int x, *p; ― ①
①のステートメントを見てみましょう。このステートメントが変数宣言を意味するのは、プログラミング学習者ならご存知だと思います。xは「int型の値を格納する変数」であり、pは「int型の変数のアドレスを格納するポインタ変数」です。
x = 4; p = &x; ― ②
②のステートメントでは、①で宣言した2つの変数に具体的な値を代入します。xにはint型の値4が代入され、pには変数xのアドレスが代入されます。「p = &x」の&はアンパサンドと呼ばれる、変数のアドレスを表す演算子です。
では、xのアドレスとはどのようなものでしょうか?
実は①で変数宣言をした時点で、2つの変数がコンピュータのメモリ上のどこかの番地に割り当てられ、プログラムが終了するまでコンピュータに記憶されます。このメモリ上の番地がアドレスです。分かりやすく例えるとアドレスはメモリ上の「住所」だと思ってもらっていいでしょう。ちなみに、どの変数がメモリ上のどこの番地に割り当てられるかはプログラムの開始時に決まるので我々はあまり気にする必要はありません。
変数は「家」⁉
変数とアドレスの関係は「家」をイメージすると理解しやすいです。変数は家、つまり「住民」を格納する箱であり、数や文字などの実際の値が変数という家の住民にあたります。そしてアドレスは変数という家の「住所」にあたるのです。ポインタ変数の場合は、参照している変数のアドレスが住民となり、ポインタ変数という家にももちろんアドレス(住所)が存在します。つまり、変数とポインタ変数の違いは住民の性質(実際の値か変数のアドレスか)の違いという訳です。
ポインタの使い方
話を戻しましょう。変数xの場合、int型(ここではint型の領域を32ビット、つまり4バイトとする)の変数であるため、メモリ上の番地4つ分にわたってxのための領域が割り当てられます。仮にその番地を2090~2093としましょう。(メモリの番地1つ分で1バイトのデータを格納するため、番地4つで4バイト。)
そして、②ではxに4という具体的な値が与えられ、pにはxのアドレスが代入されるのですが、この場合そのアドレスとは「メモリ上のxの領域の先頭アドレス」である2090になります。
このようにしてpにxのアドレスが格納されたわけですが、これによりpはxの値を参照するようになります。
printf(“%d”, x); ― ③
printf(“%d”, *p); ― ④
③と④のステートメントは同じ実行結果を示します。つまりどちらも「4」と表示するのです。(関数printf()は大丈夫ですよね?)
③はxの値4をそのまま表示するので良しとして、④はpに*のような記号が付いています。この*はアスタリスクと呼ばれる演算子で、pのようなポインタ変数に使用するとそのポインタ変数が参照している変数の値を表します。この場合、pは変数xを参照しているポインタなので、*pはxの値4を表します。また、アスタリスクは①のような変数宣言時にも使用され、この場合「pがポインタ変数である」ことを示します。
また、pはxを参照しているためxの値を別の値に更新した場合*pも自動的にその値に更新されます。
プログラムと実行結果
以上がポインタに関する説明です。変数とポインタ変数の違いについて理解できたでしょうか?復習として、簡単なプログラムとその実行結果を下に記します。
プログラム
#include<stdio.h>
int main(int argc, char *argv[]) {
int x, *p;
x = 10;
p = &x; // xのアドレスをpに格納
printf(“%d, %d, %d\n”, x, p, *p);
x = 20; // xの値を更新
printf(“%d, %d, %d\n”, x, p, *p);
return 0;
}
実行結果
10, 6422312, 10
20, 6422312, 20
※実行結果の6422312は変数xのメモリ上の領域の先頭アドレスです。pと*pの違いに注意しましょう。
いかがでしょうか?ポインタはメモリと関係があるのですね。今までポインタでつまづいていたC言語初学者もこの記事の内容を参考にもう一度プログラミングの復習をしてみましょう。プログラミングは反復が大切です。