プログラミング考え方講座「ポインタ(前編)」

プログラミング考え方講座

先に書いておく。

今回の内容は、1回読んだだけでは理解できないと思っておいて欲しい。

それほど、今回の内容は難しい

何を扱うかというと…ポインタという考え方だ。

この内容は、表面上にはC言語のみ現れるが、他の言語にも影で使われている

是非、何度も繰り返し読んで、自分に落とし込んで欲しい

スポンサーリンク

今回の説明内容

今回は、ポインタという考え方を解説する。

これは、今まで解説した変数と、今後解説するオブジェクト(構造体)においても重要な役割を持っている。

よく分からない状態で使ってしまうと、誤動作の原因になる。

逆に言えば、しっかり理解しておけばその性質を利用することもできるので、しっかり理解して欲しい。

また、以前ちらっと文字列もここで解説すると書いてしまったが…前後編に分けて、文字列配列を後編で解説しよう。

今回は前編で、ポインタをガッツリ解説していく。

ポインタ

変数の復習

以前、本講座で変数を解説した。

その時の説明は、「数字や文字列など、様々なデータを格納しておくことができる箱」というものだった。

これについて、ポインタが絡んでくると登場人物が一人増える

その箱が、どの場所に格納されているか、という情報だ。

ポインタとは

ポインタとは、変数の値が格納されている場所のことだ。住所のようなイメージで構わない。

変数定義の際の具体的な動き方を見ながら解説しよう。

ある整数型の変数numを定義する際、実際の処理は以下のような流れになる。

  • 変数の値を入れる箱が、100番地に用意される
  • 変数numを、100番地の中身を指すように設定する

そして、その変数numに5という値を入れる時は以下の通り。

  • 変数numが指す場所へアクセスする
  • アクセスした場所に、5というデータを格納する

こんな感じだ。

そのまま変数numを使うと、その100番地の中にあるデータを取り出して、5が使えるというわけだ。

このとき、「100番地」という情報が、ポインタになる。

さあ、では面白いことをしてみよう。

二つの変数num, pointerを用意する。

一つ目のnumは、上と同じく整数を入れる変数で、その住所は100番地、中には5というデータが入っているとしよう。

で、二つ目のpointerには、一つ目の変数numの、住所を入れてあげる。

つまり、pointerは200番地に用意され、100番地という情報が入っていることになる。

今の状態を表で表すと、以下の通りだ。

変数ポインタ中身
num100番地5
pointer200番地100番地

この時に、pointerの情報が指す箱の中身を入れ替えるとどうなるだろうか。

例えば、この時に「変数pointerが指す住所の中身を10に変える」という処理をしたとしよう。

そうすると、pointerが指している場所…つまり、100番地の中身が10に書き換わる

すると、上の表の内容は以下のように書き換わる。

変数ポインタ中身
num100番地5 10
pointer200番地100番地

この状態で変数numを表示するとどうなるか…もうお分かりだろう。10と表示される

このように、変数をただ単な値としてではなく、その住所を指すようにしたものが、ポインタという考え方になる。

では、このポインタをどう使うかを、具体的にC言語で見ていこう。

C言語の使用例

C言語では、明示的にポインタを使用することができる。

この時、状況によって書き方が細かく異なる。大まかな状況は以下の通り。

  • 通常の変数におけるポインタを取得する場合
  • ポインタを格納する専用の変数を用意する場合
  • ポインタが格納されている変数の、そのポインタの中にある値を取得する場合

まず、通常の変数におけるポインタを取得する場合は、その変数の先頭に&をつける。

&変数名

次に、ポインタを格納する専用の変数を用意する場合は、宣言時の変数名先頭に*をつける。

int型のポインタの場合、以下のようになる。

int *ポインタ変数名;

そして、このポインタが指す場所の中身へアクセスする場合は、ポインタ変数の先頭に*をつける。

*ポインタ変数名

これだけ書いても分かりづらいと思うので、これらを使いつつ、上に書いたnum, pointerの例をプログラムで書いてみよう。

#include<stdio.h>

int main(){
    int num = 5;
    int *pointer;
    pointer = &num;

    printf("numの値:%d\n", num);

    *pointer = 10;

    printf("numの値:%d\n", num);

    return 0;
}

これを実行すると、以下の2つが出力されるはずだ。

  • numの値:5
  • numの値:10

さあ、処理の流れはわかるだろうか。詳しく見ていこう。

まず、4行目で変数numを用意し、5を代入している。住所は、100番地としておこう。

変数名ポインタ中身
num100番地5

次に、5行目でポインタを格納する専用の変数pointerを用意している。これは200番地としよう。

変数名ポインタ中身
num100番地5
pointer200番地なし

で、6行目。&num100番地という情報を取得できるので、それを変数pointerに代入する。

変数名ポインタ中身
num100番地5
pointer200番地100番地

一度、この状態でnumの値を出力している。この時は、何も変化がないので5と表示される。

では、10行目でpointerの番地が指す先の中身を10に書き換えてみよう。

pointerは100番地を指しているので、その中身を10に置き換える。

変数名ポインタ中身
num100番地5 10
pointer200番地100番地

さあ、これでnumを出力すると…なんと、10になっている

こんなふうに、値ではなく、その値を指すポインタを用意することで、その先の中身を書き換えたりできるのだ。

…とはいえ、これだけではありがたみが薄い。

後編で解説する配列あたりから、このポインタが真価を発揮してくる。

…え?JavaとJavaScriptは解説しないのかって?

これらの言語には隠れた形で使用されているので、恐らく今解説しても混乱するだけだ。

詳細はオブジェクトの項で解説するので、今は概念だけ押さえておいて欲しい

まとめ:ポインタ

今回は、いわゆる一つの山場となるポインタについて解説した。

ポインタとは、変数の値ではなく、それが格納されている場所のことだった。

また、C言語の場合に実際に使用する例もご紹介した。

C言語を学習するつもりの方は、どの書き方で、どんなことを表すのかをしっかり意識しておいて欲しい。

次回は、いったん文字列配列について解説した後、それらとポインタの関係まで解説してしまおうと思っている。

更新情報はTwitterでも呟いている。よかったら、ページ下部のTwitterアイコンから覗いていってほしい。

それでは。

コメント

タイトルとURLをコピーしました