B−FreeOS入門書
配列とポインタ  目次へ戻る

CPUの動作を理解する上で、もうひとつ重要な物があります。
C言語などでポインタと言っている物です。
ここでは、配列も含めて説明します。

●配列と添字
プログラミング言語にはたいてい配列という物があります。たとえばBASIC言語の場合、

  Dim a(10)

と宣言する事で、a(0),a(1),a(2),...,a(9),a(10)の変数が使えるようになります。
C言語なら、

  int a[10];

と宣言する事で、a[0],a[1],a[2],...,a[9]の変数が使えるようになります。
このように、言語によって多少の違いはありますが、考え方は一緒です。
配列の利点は色々あります。
()や[]内に変数が書けるので同じ処理を繰り返しにしてまとめたり、複数のデータを1つにまとめたりする事ができます。
  1つにまとめるという意味ではC言語の構造体がより便利ですが、同じ意味をもつデータは配列にして構造体に入れたりしますので、 ここでは配列の利点として挙げました。

●ポインタとは
C言語にはポインタというものがあります。たとえば

  int *a;

と宣言する事で、aというポインタ変数が使えるようになります。
では、先ほどの配列と比べてみましょう。
   #include 
   void main()
   {
       /* 配列に値を設定します */
       int a[10] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
       int *b;
       /* a のアドレスを b に設定します */
       b = a;
       /* 内容を表示します */
       printf( "%d : %d\n", a[1], b[1] );
       printf( "%d : %d\n", a[7], b[7] );
   }
これを実行すると、

  20 : 20
  80 : 80

と表示されます。
これを見るとまったく同じ動作をしているように見えますが、まったく別の物です。
上の例で言うと、a はアドレスを表し、b はアドレスへのポインタを表します。
では、次のように b++; を追加してみましょう。
           :
       /* a のアドレスを b に設定します */
       b = a;
       /* b に設定したアドレスを intのサイズだけ加算します */
       b++;
       /* 内容を表示します */
       printf( "%d : %d\n", a[1], b[1] );
           :
これを実行すると、

  20 : 30
  80 : 90

と表示されます。
ポインタには変数の格納されているアドレスが入っているので、加算する事で指しているアドレスをずらす事ができる訳です。
試しに a++; を追加してみれば判りますが、エラーになってしまいます。

●アドレスとアドレスへのポインタ
ここまでの内容を図にして見てみましょう。
まず、最初のプログラムの例です。

 

図の a[0]〜a[9]には実際にメモリが割り当てられて、値が入っています。
ところが bに割り当てられているメモリは、アドレスを入れるためのメモリが割り当てられます。
プログラムで b = a; とあったのは、b に a のアドレスを入れる為でした。
そうする事で、上図のような関係になるわけです。

次に b++; を追加した場合を見てみましょう。

 

b++ というのは、bの内容に1を足すという意味です。
C言語の場合、ポインタ変数に1を足すというのは数値に1を足すのとは違います。
具体的には、
 ・ポインタ変数にはアドレスが格納される。
 ・したがってすべてのポインタ変数はアドレスを表せる同じサイズのメモリを使用する。
 ・ポインタ変数の型はポインタ変数が示す先に格納されているデータの型である。
  (要はポインタ変数の型はポインタ変数そのものの型ではないという事)
 ・ポインタ変数に1を加算するという事は、次のデータのアドレスを格納する事である。
  (要はポインタ変数の型に対応するサイズが加算されるという事)
となっています。

では printfで表示した時の関係を見てみましょう。
 

a[1],b[1],a[7],b[7]がそれぞれどこを示しているかに注意してください。
これまで[n]を添字と言っていましたが、実はポインタ変数のアドレス計算とまったく同じ考え方で動いています。
違いは、変数そのものの内容が変わらない事だけです。
  それではBASIC言語の可変長文字列の配列の場合はどうでしょう。
普通に考えると可変長だからサイズも可変なのでこれまでの説明ではうまくいかないのでは?と思いますよね。
でもこれはポインタ変数の配列を作ってしまえば実現できるのです。
ここまで説明した通り、ポインタそのものはサイズ固定なので配列にできます。
そして個々の変数に文字列の先頭アドレスを入れれば良いのです。

●ポインタとレジスタの関係
前回CPUを構成する物としてレジスタを説明しました。
レジスタは計算だけでなく今回説明したポインタのような使い方もかなりの頻度で使用します。
「ポインタが示すメモリの内容が示すアドレスの内容」のような使い方をする場合も良くあるので、 良く理解しておいて下さい。
(とは言っても「ポインタが示す位置にポインタがある」事があるというだけの事です。)
目次へ戻る