a[] という配列変数があったとする。このとき, *(a+1) は a[1] と正確に同じ意味になる。 従って, 配列の n+1 番目の要素を参照したければ *(a+n) となる (このとき,n は int 型の変数でなければならない)。 array_pointer.c
整数型の配列 a[3] と整数型へのポインタ aPtr が宣言されているとする。
添字なしの配列名はその配列の先頭要素へのポインタである。
なので,以下の文のように配列 a の先頭アドレスを aPtr にセットすることができる。
aPtr = a;
これは配列の先頭要素のアドレスを使った以下の文と同義である。
aPtr = &a[0];
このとき,配列要素 a[2] は次のポインタの式でも参照可能である。
*(aPtr + 2)
この式中の 2 は,ポインタ aPtr からどのくらい離れているかを表す数字なり オフセットと呼ばれたりする。 オフセットの数字と配列の添字とは等しい。 * 演算子の方が + 演算子よりも優先順位が高いので「aPtr+3」を括弧で囲む必要がある。 括弧がないと
*aPtr + 2
は,*aPtr に 2 を足すという意味に解釈されてしまう。 すなわち aPtr は配列の先頭を指しているので a[0] に 2 を加えた数が返される。 ポインタを使って配列の要素にアクセスできるように,
&a[2]
も以下のようにポインタを使って,
aPtr + 2
のように表現できる。
配列名自体もポインタとして扱えるので,ポインタ演算を使うことができる。 たとえば,次の式
*(aPtr + 1)
は,先に述べたように a[1] と同義である。サンプルコードを以下に示す。
pointer_array.c
逆に,ポインタを配列として記述することも可能である。例えば
aPtr[1]
は,配列要素 a[1] を参照する。
このような書き方をポインタの添字表記法と呼ぶ。
配列表記とポインタ表記を使った文字列のコピーのサンプルコードを以下に示す。
pointer_copy.c
array_pointer.c の printf() 文の a[0], a[1], a[2] を p[0], p[1], p[2] にして実行せよ。
ポインタ p | 配列 a | |
---|---|---|
配列の先頭要素のアドレス | p または &p[0] | a または &a[0] |
配列の先頭要素 | *p または p[0] | *a または a[0] |
次の例は,a[3] という要素の数が 3 である配列 a[3] に対して,intPtr というポインタ変数
に a (すなわち a の先頭の要素のアドレス &a[0])を代入し,その値を調べて,それぞれのアドレスと値を印刷している。
array_pionter2.c
また,次のサンプルプログラムも配列 a[3] の中の 1 番目の要素 a[0] のアドレスと要素の値を印刷している。
array-pionter3.c
int a[] を引数に持つ関数(例えば
max-array-func.c)は,
仮引数に int a[], または int *a として,
実引数は配列名 a とする。call by reference の説明で述べたように,
仮引数の int *a は配列 a を指すポインタであり,
実引数の a は配列 a のアドレスである。
次のサンプルプログラムは, array[i] に代入した値を *(arrayPtr+i) で表示している。
array_pointer4.c
次のサンプルコードはやや複雑にしてある。*arrayPtr は array[10] という配列へのポインタ変数である。従って、*arrayPtr++; は array[10] を参照し,インクリメント ++ することにより,各要素を順に表示している。またその時のアドレスを arrayPtr+i で表示している。
array_pointer5.c
次の例は arraysum() という関数に渡す引数として main 関数では a[N] と配列で宣言してある a を,arraysum() 関数の定義実体ではポンンタとして受け取っている。
array-sum.c
selection-sort.cをポインタを用いて書き換えよ。 解答例
次のサンプルコードは char str[4][30]={"こんにちは", "世界", "私の名前は", "浅川だ"};
という文字列の配列を扱ったものである。この例は,
str[0]="こんにちは",
str[1]="世界",
str[2]="私の名前は",
str[3]="浅川だ",
という 4 つの文字列を要素とする配列である。char *strPtr とすれば,
str の i 番目の要素を strPtr に代入し,
strPtr = *(str+i)
とすることで
printf("%s", str[i]); と
printf("%s", strPtr); とは同じ動作をする。
strPtr20081201-01.c
上の例の printf() 文を putchar() 文で置き換えて,ポインターの操作と文字列の配列の操作を示した例が以下のサンプルコードである。
strPtr20081201-02.c
strPtr20081201-03.c
strPtr20081201-04.c
strPtr20081201-05.c
strPtr20081201-06.c
ポンターへのポインターということでしばしば混乱が起こる。
注意してソースコードを読む必要がある。
次のサンプルコードは 2 次元配列 mat[3][3] に対するポンターとして,
int *intPtr, **intPtrPtr; を定義している。
double_pointer1.c
文字列へのポンターへのポインターを定義して,ポインタの演算をしているサンプルコードを以下に示す。
double_pointer2.c
double_pointer3.c