配列を使う(配列はポインタ)


 えー、前回までにポインタの意味を説明したので、これにより最大の恩恵を受けている(?)配列と、構造体のうち、今回は配列に的を絞って解説したいと思います。配列を使う上での最大のメリットは文字列が扱えるようになることだと思います。ですが、いきなり、char 型の配列に行かないで int 型の配列で、ある変数が値を表しているのか、アドレスを表しているのかを見極める目を鍛えたいと思います。

 サンプルコードに移る前に、説明したいことを文章で表します。まず、次のような変数を宣言します。

int a, b[10], c;

見ての通り、int 型の変数、「a」「b」「c」です。同じ型であればカンマで区切って一文で宣言できるのは、ご存じでしょうか? 余談はおいておいて、「b」は配列になっています。前2つの変数の値を参照して、「c」と言う変数に値を代入したいと思います。普通の変数ならば
c = a;

となるはずです。ここは合点してもらえると思います。次に配列の一番目を変数「c」に代入したいと思います。今回は、
c = b[0];

となります。配列は宣言で10個と指定したので配列のインデックス番号は0番から9番となります。気をつけて下さい。ここまでは、OKですね? そこで、次は int 型のポインタを宣言してその変数のアドレスをコピーしたいと思います。
int *p;

これで、int 型のポインタ「p」を宣言しました。では、コピーをしますが、アドレスを表す時ははアドレス演算子「&」を変数の前につけます。
p = &a; p = &b[0];

これにより、「p」にアドレスをコピーした事になります。配列は書くことが多くて面倒くさいですね。実は配列では次のような書き方も出来ます。
p = b;

ここが肝腎です。配列「b」のアドレスを参照する場合、
p = &b[0]; p = b;

の、2文は同じ意味になります。これがサブタイトルにつけた
配列はポインタ
の最大の理由です。よって、次のような宣言の関数があるとします。
int computeSum( int *data );

この関数を呼び出す場合、引数は int 型のポインタとなっているので、次のような呼び出しかたをします。
c = computeSum( &a );
c = computeSum( &b[0] );
c = computeSum( b );

2番目と3番目が同じ意味を表しています。いいですか? では、2番目を3番目をどう使い分けるか。 3番目の方が楽だから、2番目のやり方は使わない訳ではありません。配列のメンバの途中から、関数に渡したい、即ち、computeSum 関数が合計を計算する関数だとすると、初めの5つのデータは無視して、 後半の5つのデータを計算したい時には、次のように呼び出します。
c = computeSum( &b[5] );
(注意:computeSum 関数を作るにあたって、その関数内では配列「b」の個数を知ることは出来ないので、関数の引数に何個分を計算するかなどの情報も渡してやる必要があります。文字列、char 型の変数では文字列の終わりを NULL で表しています。この辺は文字列の話で、いずれ・・・。)

 それでは、最後に「p」には「a」又は「b[0]」のアドレスが入っていますが、そのアドレスの値を参照したいと思います。ポインタにどんな値が入っているかを知りたいときは間接演算子「*」を用いて参照します。ポインタ変数「p」が指すアドレスに入っている数値を変数「c」にコピーしてみましょう。

c = *p;

ここまでの説明、わかりましたか?以上でポインタと配列の話を終わりたいと思います。

 下に、サンプルコードをこの文章に従って作成しました。実際にコードをコンパイルして、出力されたデータが自分の考えと一致しているかを確認して下さい。前回同様、見栄えをよくするために全角スペース等を使っているのでご使用のブラウザから直接コピーするとコンパイルエラーが出ますので、あしからず。ソースの下の方に”c = p”と間違いを入れました。コンパイラによっては、ワーニング(警告)が出るかと思いますが、構わず、実行して下さい。異常、又は、実行するのに不安な方は、出力文と共に削除して下さい。

サンプルコード
<配列はポインタ>
ソースファイル(0.7K-Byte)
------------------------------ sample3.c START ------------------------------

    #include
    
    main ()
    {
      int a, b[10], c;
      int* p;
    
      a = 5;         /* 初期値代入 */
      b[0] = 7;       /* 初期値代入 */
      b[1] = 9;       /* 初期値代入 */
    
      c = a;
      printf( "output1 = %d\n", c ); /* "output1 = 5"と出るはず */
    
      c = b[0];    /* 配列1番目 */
      printf( "output2 = %d\n", c ); /* "output2 = 7"と出るはず */
    
      p = &a;
      p = *p;
      printf( "output3 = %d\n", c ); /* "output3 = 5"と出るはず */
    
      p = &b[1];   /* 配列2番目 */
      c = *p;
      printf( "output4 = %d\n", c ); /* "output4 = 9"と出るはず */
    
      p = b;     /* 配列1番目!! */
      c = *p;
      printf( "output5 = %d\n", c ); /* "output5 = 7"と出るはず */
    
      c = p;     /* これは、間違い */
      printf( "output6 = %d\n", c ); /* 出力不明 */
    
      return 1;    /* お約束 (^m^;) */
    }
------------------------------ sample3.c END ------------------------------

配列はポインタ、サンプルコード

C言語講座トップページ

TOP-PAGE

Web-Page制作者e-mailアドレス