第9回資料

C言語応用
ポインタと配列
ポインタと配列
次のように宣言された、大きさ10
である int 型の配列 x と、int への
ポインタ p を考える。
int x[10];
int *p
ここで
x[0]
x[1]
:
:
x[9]
p = &x[0];
とする。p は x[0] を指しますから、
*p は x[0] のエイリアスとなります。
p
*p
ポインタと配列
 ポインタ ptr に、整数 i を加えて減じたりした式も
ポインタとなります。
ptr+i は、ptr が指すオブジェクトの i 個
後ろの要素を指すポインタとなる。
ptr-i は、ptr が指すオブジェクトの i 個
前の要素を指すポインタとなる。
x[0]
*p
x[1]
*(p+1)
x[9]
ここで考えている例では、たとえば
p+1 は x[1] を、p+5 は x[5] を指す
ことになる。
p
*(p+9)
ポインタと配列
 ptr がポインタで、i が整数であるとき、次のような
規則が成り立つ。
x[0]
*p
p[0]
x[1]
*(p+1)
p[1]
x[9]
*(p+9)
p[9]
p
*(ptr+i) は ptr[i] とも表記できる。
配列の名前
 配列に関しても、重要な規則がある。
プログラム中に[ ]を伴わずに単独で現れた配列
名は、その配列の先頭要素へのポインタとみな
される。
たとえば、x が配列であるとき、x は、先頭要素
x[0] へのポインタ、すなわち &x[0] を意味する。
配列の名前
 補足
原則として、プログラム中に[ ]を伴わずに単独で現れた配列
名は、その配列の先頭要素へのポインタとなるが、若干の例
外がある。
(1) sizeof 演算子のオペランドであるとき
sizeof 演算子は、オペランドとして配列が与えられた時は、その
配列の大きさを生成する。たとえば、sizeof(int) が2であるとき、
int a[10];
printf(“%d\n”,sizeof(a));
は、20を出力します。
(2) &演算子のオペランドであるとき
配列名に&演算子が適用されると、その配列全体へのポイン
タを生成します(配列の先頭要素へのポインタではない)。
引数としての配列
list6-5.c のプログラムでの、search 関数について
search 関数を呼び出す所に着目すると、
no = search(atensu,AMAX,50);
となっており、最初の引数 atensu は、配列 atensu の先頭要素
である atensu[0] へのポインタである。したがって配列の先頭
要素へのポインタ &atensu[0] が渡されている。
呼び出される側の search 関数は、引数 mark にそのポインタ
を受け取ります。実は、search 関数の頭部は
int search(int *mark, int max, int ten)
と記述できます。int mark[] と宣言しても int *mark と宣言しても、
全く同じことになるのです。
引数としての配列
 重要
関数間での配列の受け渡しは、先頭要素へのポ
インタという形で行う。受け取る側の関数は、その
ポインタに対して[ ]演算子を適用することによって、
あたかも配列のように扱うことができる。
演習
 2つの int 型の配列 a,b と、その大きさを受け取り、
b の全要素を、aの各要素にコピーする関数
void icopy(int *a,int *b, int n){・・・}
を作成せよ。
 2つの int 型の配列 a,b と、その大きさを受け取り、
全要素を入れ換える関数
void iswap(int *a,int *b, int n){・・・}
を作成せよ。