1.6 ポインタ Menuへ戻る

  ポインタは非常に奥が深く、不可解な物であります。しかし、Cプログラマの
技量はどれほどポインタのテクニックを知っているかで決まるでしょう。

  C、C++、MFC とこれからの言語において重要であり、これを知っているか
どうかで今後の話を理解できるかどうかが決まるでしょう。ここでは概略を説明
します。


  まず、パソコンのモデルを説明しましょう。図1をみて下さい。

    +-------------+         +----------+
    |   C P U |---------| メ モ リ  |
    +-------------+         +-----+----+
                                  |
                                  |
                            +-----+-----+
                            | 外部メモリ |
                            +-----------+

  となっています。外部メモリとは通常ハードディスクなどの記憶装置の事を
指します。主メモリは高速で低容量、外部メモリは低速で大容量というトレー
ドオフの関係にあります。一般的に変数などはメモリ上に確保されます。整数
型なら4バイト、文字型なら1バイトのメモリ領域を使用します。

  ちなみにプログラム本体は必要時に主メモリに読み込まれ、実行されます。
この作業がエクスプローラでのダブルクリックにあたります。さて、プログラ
ムの中では気軽に iValue = 200 と書きますが、これは内部的にはどうなって
いるのでしょうか?

  iValue という変数が割り当てられているメモリ領域に整数 0x000000c8 を代
入してください。という事になります。ちなみに 0x000000c8 は 200 の 32bit
の16進数表示です。さて、ここで問題なのは

  iValue という変数が割り当てられているメモリ領域
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  の部分です。 iValue には 200 という数値情報しか持ちません。CPU はどう
やって iValue にあたるメモリ領域を決定するのでしょうか???

  これと同じ事が実生活でも起こります。誰かの家、仮にAさんとしましょう。
私がAさんに200円送る。という事をしたいとき、私はどこに送ればいいか
わかりません。ここで使うのは住所録です。これを使えばどこに送ればいいかが
わかります。

  Cにおいても同じ事で、変数にはそれぞれ番地情報が付いているのです。いわ
ゆるメモリ内住所とでもいいましょうか。つまり変数を宣言すると同時に番地情
報も作られるのです。当たり前の事で、家を建てたら住所ができます。CPU はそ
の住所によってどこに数値を入れればいいのかを知ります。

  そして、その番地情報を「ポインタ」といいます。メモリ内の位置を指し示す
物という意味だと思われます。通常変数の頭に&を付けた物がポインタです。実
生活の様に住所録を引かなくても&をつけるだけで番地情報が得られるのです。

  さて、ここで疑問に思う人もいるかもしれません。CPUが使うはずの番地情
報を我々が使う必要があるのか?という事です。初めの内は全く使う必要がない
と思っていました。が、いろいろな物を見ていく内に溢れんばかりのポインタが
登場する事となります。そのためにもキッチリとマスターして下さい。

  int iValue;

  と宣言すると iValue は整数型変数、&iValue は ポインタ

  char cMoji;

  と宣言すると cMoji は 文字型、&cMoji はポインタ、となります。

  また、ポインタだけ作る事もできるのです。この使い方が一番多いかもしれま
せん。宣言の時に*を付けて宣言すると変数が格納されるメモリ領域を作らずに、
どこかのメモリ内の位置を指し示すだけのポインタを作る事ができます。

  int*  pInt;  /* ポインタの作成 */
  int   iValue;/* 変数の作成 */

  pInt = &iValue ; /* 作ったポインタに変数(iValue)のポインタを代入 */

  こうすると pInt は iValue を指し示すポインタとなります。よって2つの
ポインタ &iValue と pInt は同じ位置、つまり iValue の中身のあるメモリ位置
へのポインタとなります。

  しかし pInt は所詮ポインタなので、これではあまり意味がありません。こ
いつが指し示す内容を変更するために

  pInt = 200;

  と書くと間違いです。pInt はポインタですから数値を入れても意味がありません。
ここで「ポインタの指し示すメモリ内容」を意味するのは、また*です。*をポ
インタの頭に付けると「ポインタの指し示すメモリ内容」という事になります。

  *pInt = 200;

  これをすると pInt が指し示すメモリに 200 と入ります。同時に同じ内容であ
る &iValue の指し示す iValue も変更されます。ちょっと難しいですがわかった
でしょうか???

  以下にサンプルを書きますので、これを見ながらいろいろと考えて下さい。

#include <stdio.h>

void main()
{
    int   iValue; /* 整数型変数 */
    int*  pInt; /* ポインタ */

    iValue = 500; /* 500という数を入れる */
    printf("現在の iValue = %d\n",iValue);

    pInt = &iValue ;/* 用意したポインタに変数のポインタを代入した */

    printf ("pInt の 指し示す内容(1) = %d\n",*pInt);/* *で指し示す内容 */

    *pInt = 999;/* pInt の指し示す内容を変えてやる */
    printf ("pInt の 指し示す内容(2) = %d\n",*pInt);/* *で指し示す内容 */

    printf("現在の iValue = %d\n",iValue);

}

  一連の流れが理解できるまで、いろいろと変えてみながら試して下さい。この部分
がわからないと致命的です。わからない事など質問して下さい。この部分は一つのメ
モリ内容を2つのポインタで操作できるという事を意味します。これはプログラムの
中で、一つのデータを多方向から読み書きするという形に近いです。この様に高度な
プログラミングにはポインタは欠かせません。次回はもっとハードに文字列と配列と
ポインタです。

i.e. 文章の中でCPUと書いている部分は実はコンパイラの仕事です。変数と番地
     の対応付けの部分はコンパイラがやっているのです。

i.e. ポインタという物の実体は CPU - MEM のアドレスバスが 32bit のマシンは
     32bit の変数です。実際見てやれば見る事もできます。もちろん最大値は
     搭載しているメモリ容量によって変わります。