3 さまざまなポインター

3.1 単純型変数へのポインター

単純型変数--文字型や整数型,倍精度実数型など--へのポインターは,説明するまでも ないだろう.1年生の授業で学習したし,先ほどの例でも示した.そのため,ここでは単 純型変数へのポインターについては,説明しない.

3.2 構造体へのポインター

構造体へのポインターはしばしば使われ,プログラムを分かりやすくするためには重要で ある.実際には,中間試験以降のデータ構造の学習では頻繁にこれを使うことになる.

構造体のポインターの例をリスト3にしめす.図 2にポインターと構造体の関係を示す.リストを見て分かるように, 構造体へのポインターは次のようにして使う. -4pt


   1 #include <stdio.h>
   2 
   3 int main(void)
   4 {
   5   typedef struct{                        // 構造体の定義
   6     char name[16];
   7     int math;
   8     int info;
   9   }student;
  10 
  11   student yama={"yamamoto",72,83};       // 宣言と初期化
  12   student *p;                            // 構造体 student 型へのポインター
  13 
  14   p=&yama;                               // 先頭アドレスの代入
  15 
  16   printf("name = %s\n", p->name);        // メンバーへのアクセスは,アロー演算子
  17   printf("math = %d\n", p->math);
  18   printf("info = %d\n", p->info);
  19 
  20   return 0;
  21 }


\fbox{実行結果}
name = yamamoto
math = 72
info = 83
図 2: ポインターpと構造体のオブジェクトstudentの関係.
\includegraphics[keepaspectratio, scale=1.0]{figure/pt_struct.eps}

3.3 配列へのポインター

ここはかなり混乱しそうなので,ほとんど説明しないでおこう.もう少しC言語の理解が 深まったならば,各自,勉強すればよい.配列との関係で重用なことは,配列のコンピュー ターでの処理は

hoge[i]$\displaystyle \qquad\Rightarrow$   *(hoge+i)    

となることである.

3.4 関数へのポインター

諸君にとって,最もけったいに感じるのが関数へのポインターであろう.実行すべき命令 が書かれている関数もメモリーにロード--読み込んで格納--される.したがって,先 頭アドレス--関数のエントリー--をポインターに代入することができる.
   1 #include <stdio.h>
   2 
   3 int add(int i, int j);             // プロトタイプ選言
   4 
   5 //============ メイン関数===============================
   6 int main(void)
   7 {
   8   int (*fp)(int, int);             // 関数へのポインター
   9 
  10   fp=add;                          // 関数のアドレスを代入
  11 
  12   printf("%d\n",fp(5,9));
  13   
  14 
  15   return 0;
  16 }
  17 
  18 //============ ユーザー定義関数==========================
  19 int add(int i, int j)
  20 {
  21   return i+j;
  22 }


\fbox{実行結果}
14

これは使い方によってはかなり便利である.サブルーチンへ関数を渡すことが可能となる. リスト5がそれを使った例である.ここで,関数定義の仮引数の double (*f)(double)が関数へのポインターの宣言で,

戻り値の型 (*関数へのポインター変数)(引数の型)
と書く.この関数へのポインター変数に関数のポインター--先頭アドレス--を代入する と,ポインター変数が関数のように使える.関数のポインターへの代入は関数名を右辺値 として,代入するだけである.
   1 #include <stdio.h>
   2 #include <math.h>
   3 
   4 void print_func(double (*f)(double));  // プロトタイプ選言
   5 
   6 //======== メイン関数 ========================================
   7 int main(void)
   8 {
   9 
  10   print_func(sin);
  11   print_func(cos);
  12 
  13   return 0;
  14 }
  15 
  16 //========== 関数の値を表示する関数 ============================
  17 void print_func(double (*f)(double))
  18 {
  19   int i;
  20   double dx=0.1;
  21 
  22   printf("--------------------------\n");
  23   for(i=0; i<=5; i++){
  24     printf("%f\t%f\n", i*dx, f(i*dx));
  25   }
  26 }


\fbox{実行結果}
--------------------------
0.000000        0.000000
0.100000        0.099833
0.200000        0.198669
0.300000        0.295520
0.400000        0.389418
0.500000        0.479426
--------------------------
0.000000        1.000000
0.100000        0.995004
0.200000        0.980067
0.300000        0.955336
0.400000        0.921061
0.500000        0.877583

3.5 ポインターの配列

複数組の文字列を扱う場合,ポインターの配列は便利である.リスト 6にプログラム例を,図3にポインターと文字列定 数の関係を示す.ここでの動作は次のようになる.
   1 #include <stdio.h>
   2 
   3 int main(void)
   4 {
   5   char *animal[]={"cat", "dog", "rabbit", "horse"};
   6 
   7   printf("1st : %s\n", animal[0]);
   8   printf("2nd : %s\n", animal[1]);
   9   printf("3rd : %s\n", animal[2]);
  10   printf("4th : %s\n", animal[3]);
  11 
  12   return 0;
  13 }


\fbox{実行結果}
1st : cat
2nd : dog
3rd : rabbit
4th : horse
図 3: 文字列定数とポインターの配列animalの関係.
\includegraphics[keepaspectratio, scale=1.0]{figure/pt_array.eps}

3.6 ポインターのポインター

ポインターを指し示すポインターがある.これは,つぎのように書く.
	int **hoge, *fuga, a;
	
	fuga=&a;
	hoge=&fuga;

あまり深入りしないことにする.


ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
平成19年5月29日


no counter