先に書いておく。
今回の内容は、1回読んだだけでは理解できないと思っておいて欲しい。
それほど、今回の内容は難しい。
何を扱うかというと…ポインタという考え方だ。
この内容は、表面上にはC言語のみ現れるが、他の言語にも影で使われている。
是非、何度も繰り返し読んで、自分に落とし込んで欲しい。
今回の説明内容
今回は、ポインタという考え方を解説する。
これは、今まで解説した変数と、今後解説するオブジェクト(構造体)においても重要な役割を持っている。
よく分からない状態で使ってしまうと、誤動作の原因になる。
逆に言えば、しっかり理解しておけばその性質を利用することもできるので、しっかり理解して欲しい。
また、以前ちらっと文字列もここで解説すると書いてしまったが…前後編に分けて、文字列と配列を後編で解説しよう。
今回は前編で、ポインタをガッツリ解説していく。
ポインタ
変数の復習
以前、本講座で変数を解説した。
その時の説明は、「数字や文字列など、様々なデータを格納しておくことができる箱」というものだった。
これについて、ポインタが絡んでくると登場人物が一人増える。
その箱が、どの場所に格納されているか、という情報だ。
ポインタとは
ポインタとは、変数の値が格納されている場所のことだ。住所のようなイメージで構わない。
変数定義の際の具体的な動き方を見ながら解説しよう。
ある整数型の変数num
を定義する際、実際の処理は以下のような流れになる。
- 変数の値を入れる箱が、100番地に用意される
- 変数
num
を、100番地の中身を指すように設定する
そして、その変数num
に5という値を入れる時は以下の通り。
- 変数
num
が指す場所へアクセスする - アクセスした場所に、5というデータを格納する
こんな感じだ。
そのまま変数num
を使うと、その100番地の中にあるデータを取り出して、5が使えるというわけだ。
このとき、「100番地」という情報が、ポインタになる。
さあ、では面白いことをしてみよう。
二つの変数num
, pointer
を用意する。
一つ目のnum
は、上と同じく整数を入れる変数で、その住所は100番地、中には5というデータが入っているとしよう。
で、二つ目のpointer
には、一つ目の変数num
の、住所を入れてあげる。
つまり、pointer
は200番地に用意され、100番地という情報が入っていることになる。
今の状態を表で表すと、以下の通りだ。
変数 | ポインタ | 中身 |
---|---|---|
num | 100番地 | 5 |
pointer | 200番地 | 100番地 |
この時に、pointer
の情報が指す箱の中身を入れ替えるとどうなるだろうか。
例えば、この時に「変数pointer
が指す住所の中身を10に変える」という処理をしたとしよう。
そうすると、pointer
が指している場所…つまり、100番地の中身が10に書き換わる。
すると、上の表の内容は以下のように書き換わる。
変数 | ポインタ | 中身 |
---|---|---|
num | 100番地 | |
pointer | 200番地 | 100番地 |
この状態で変数num
を表示するとどうなるか…もうお分かりだろう。10と表示される。
このように、変数をただ単な値としてではなく、その住所を指すようにしたものが、ポインタという考え方になる。
では、このポインタをどう使うかを、具体的にC言語で見ていこう。
C言語の使用例
C言語では、明示的にポインタを使用することができる。
この時、状況によって書き方が細かく異なる。大まかな状況は以下の通り。
- 通常の変数におけるポインタを取得する場合
- ポインタを格納する専用の変数を用意する場合
- ポインタが格納されている変数の、そのポインタの中にある値を取得する場合
まず、通常の変数におけるポインタを取得する場合は、その変数の先頭に&
をつける。
&変数名
次に、ポインタを格納する専用の変数を用意する場合は、宣言時の変数名先頭に*
をつける。
int型のポインタの場合、以下のようになる。
int *ポインタ変数名;
そして、このポインタが指す場所の中身へアクセスする場合は、ポインタ変数の先頭に*
をつける。
*ポインタ変数名
これだけ書いても分かりづらいと思うので、これらを使いつつ、上に書いたnum
, pointer
の例をプログラムで書いてみよう。
#include<stdio.h>
int main(){
int num = 5;
int *pointer;
pointer = #
printf("numの値:%d\n", num);
*pointer = 10;
printf("numの値:%d\n", num);
return 0;
}
これを実行すると、以下の2つが出力されるはずだ。
- numの値:5
- numの値:10
さあ、処理の流れはわかるだろうか。詳しく見ていこう。
まず、4行目で変数num
を用意し、5を代入している。住所は、100番地としておこう。
変数名 | ポインタ | 中身 |
---|---|---|
num | 100番地 | 5 |
次に、5行目でポインタを格納する専用の変数pointer
を用意している。これは200番地としよう。
変数名 | ポインタ | 中身 |
---|---|---|
num | 100番地 | 5 |
pointer | 200番地 | なし |
で、6行目。&num
で100番地という情報を取得できるので、それを変数pointer
に代入する。
変数名 | ポインタ | 中身 |
---|---|---|
num | 100番地 | 5 |
pointer | 200番地 | 100番地 |
一度、この状態でnum
の値を出力している。この時は、何も変化がないので5と表示される。
では、10行目でpointer
の番地が指す先の中身を10に書き換えてみよう。
pointer
は100番地を指しているので、その中身を10に置き換える。
変数名 | ポインタ | 中身 |
---|---|---|
num | 100番地 | |
pointer | 200番地 | 100番地 |
さあ、これでnum
を出力すると…なんと、10になっている。
こんなふうに、値ではなく、その値を指すポインタを用意することで、その先の中身を書き換えたりできるのだ。
…とはいえ、これだけではありがたみが薄い。
後編で解説する配列あたりから、このポインタが真価を発揮してくる。
…え?JavaとJavaScriptは解説しないのかって?
これらの言語には隠れた形で使用されているので、恐らく今解説しても混乱するだけだ。
詳細はオブジェクトの項で解説するので、今は概念だけ押さえておいて欲しい。
まとめ:ポインタ
今回は、いわゆる一つの山場となるポインタについて解説した。
ポインタとは、変数の値ではなく、それが格納されている場所のことだった。
また、C言語の場合に実際に使用する例もご紹介した。
C言語を学習するつもりの方は、どの書き方で、どんなことを表すのかをしっかり意識しておいて欲しい。
次回は、いったん文字列と配列について解説した後、それらとポインタの関係まで解説してしまおうと思っている。
更新情報はTwitterでも呟いている。よかったら、ページ下部のTwitterアイコンから覗いていってほしい。
それでは。
コメント