このことを具体例をつかって,説明しよう.リスト7のプログ
ラムでは,pがポインター変数でhogeがオブジェクトである.この関係は図
1のように表すことができる.
1 #include <stdio.h> 2 3 int main(void) 4 { 5 int hoge=3; 6 int *p; 7 8 p=&hoge; 9 10 printf("hoge=%d\n",*p); 11 12 return 0; 13 }
hoge=3
このような結果が得られるのは,リスト7の10行目でポインター pがhogeを指し示すからである.オブジェクトとポインターの関係は8行目で hogeで決められている; オブジェクトの先頭アドレス3 をポインター変数に代入している.
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 }
name = yamamoto math = 72 info = 83
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 }
14
これは使い方によってはかなり便利である.サブルーチンへ関数を渡すことが可能となる. リスト10がそれを使った例である.ここで,関数定義の仮引数の 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 }
-------------------------- 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
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 }
1st : cat 2nd : dog 3rd : rabbit 4th : horse
C言語では大雑把に言って,コード(code)、データ(data)、ヒープ(heap)、スタック (stack)の4つの領域にメモリーを分けて,管理する.これらの使い分けに,プログラマー はほとんど気にする必要はない.ただし,変数--配列や構造体を含む--を使う場合, メモリーは次のような使い方があると,プログラマーは認識しておくべきである. -4pt
大きな配列を使いたい場合,ヒープ領域をつかう.malloc()関数によりメモリーを
確保して,free()関数によりメモリーを開放する.その例をリスト
12に示す.
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(void) 5 { 6 int *a; 7 8 a=malloc(sizeof(int)*1024*1024*10); 9 10 a[0]=1; 11 printf("a[0]=%d\n",a[0]); 12 13 free(a); 14 15 return 0; 16 }
a[0]=1malloc()関数を使って,メモリーを確保している.ただし,この関数でいつも思い 通りのメモリーを確保できるとは限らない.この関数は,メモリー確保に失敗した場合,NULLポ インターを返す.