「アルゴリズム」資料 2(f)C の配列とポインタ
鴨浩靖

2009 年 10 月 6 日 初版
2011 年 10 月 4 日 第二版
2012 年 10 月 1 日 第三版
2012 年 10 月 2 日 第三版改2020 年 10 月 12 日 第四版

1 / 21

配列とポインタ
C 言語では、式の中で配列名が使われると、その配列の最初の要素へのポインタと解釈される。

例
int
int

a[10];*p;と定義されているとき、

p = a;とp = &a[0];は同じ意味。

2 / 21

ポインタに整数を足す
配列の要素を指しているポインタ値に整数値を足すと、結果は加えた整数値だけ添字を進めた要素を指すポインタ値になる。

例
int
int

a[10];*p;と定義されていて、p の値が a[3] を指すポインタであるときに、
p + 2 を計算すると、結果は a[5] を指すポインタになる。

01234567893 / 21

ポインタから整数を引く
配列の要素を指しているポインタ値から整数値を引くと、結果は引いた整数値だけ添字を戻した要素を指すポインタ値になる。

例
int
int

a[10];*p;と定義されていて、p の値が a[3] を指すポインタであるときに、
p - 2 を計算すると、結果は a[1] を指すポインタになる。

01234567894 / 21

ポインタからポインタを引く
配列の要素を指しているポインタ値から同じ配列の要素を指しているポインタ値を引くと、結果は添字の差にあたる整数値になる。

例
int
int

a[10];*p, *q;と定義されていて、p の値が a[5] を指すポインタであり、q の値が a[1] を指すポインタであるときに、p - q を計算すると結果は 4 になる。q - p を計算すると結果は −4 になる。
01234567895 / 21

ポインタからポインタを引く（つづき）
二つのポインタ値が同じ配列の要素を指すものでなければ、引き算して何が起きるかは処理系に依存する。

例
int
int
inta[10];b[20];*p, *q;と定義されていて、p の値が a[5] を指すポインタであり、q の値が b[1] を指すポインタであるときに、p - q を計算して何が起きるかはわからない。

6 / 21

ポインタとポインタの大小比較
配列の要素を指しているポインタ値と同じ配列の要素を指しているポインタ値の大小比較の結果は、添字の大小比較の結果と一致する。

例
int
inta[10];*p, *q;と定義されていて、p の値が a[5] を指すポインタであり、q の値が a[1] を指すポインタであるときに、p < q を計算すると、結果は 0 になる。p >= q を計算すると、結果は 1 になる。

01234567897 / 21

ポインタとポインタの大小比較（つづき）
二つのポインタ値が同じ配列の要素を指すものでなければ、大小比較で何が起きるかは処理系に依存する。

例
int
int
int

a[10];
b[20];*p, *q;と定義されていて、p の値が a[5] を指すポインタであり、q の値が b[1] を指すポインタであるときに、p < q を計算して何が起きるかはわからない。

8 / 21

配列の要素の総和a[] の総和を計算して、s に代入したい。
▶ 添字を動かすinti;
s = 0;for (i = 0; i < 100; i ++) {s += a[i];}▶ ポインタを動かす
int*p;s = 0;for (p = &a[0]; p < &a[100]; p ++) {s += *p;}

9 / 21

配列の要素の総和（つづき）
以下は、書き方が違うだけで全く同じ意味。
▶ ポインタを動かす

int*p;s = 0;for (p = &a[0]; p < &a[100]; p ++) {s += *p;}▶ ポインタを動かす
int*p;s = 0;for (p = a; p < a + 100; p ++) {s += *p;}

10 / 21配列から配列へのコピー▶ 添字を動かすinti;for (i = 0; i < 100; i ++) {b[i] = a[i];}▶ ポインタを動かす
int*p, *q;for (p = a, q = b; p < a + 100; p ++, q ++) {*q = *p;}

11 / 21配列から配列へのコピー（つづき）▶ memcpy() を使う。
#include <string.h>が必要。

memcpy(b, a, sizeof(int) * 100);

12 / 21配列から配列へ各要素を 2 個ずつコピー▶ 添字を動かすinti;for (i = 0; i < 100; i ++) {b[i * 2] = a[i];b[i * 2 + 1] = a[i];}▶ 添字を動かす（別解）
int
i, j;
for (i = 0, j = 0; i < 100; i ++, j += 2) {b[j] = a[i];b[j + 1] = a[i];}13 / 21配列から配列へ各要素を 2 個ずつコピー（つづき）▶ 添字を動かす（別解 2）
int
i, j;
for (i = 0, j = 0; i < 100; i ++) {b[j] = a[i];j ++;
b[j] = a[i];j ++;}14 / 21配列から配列へ各要素を 2 個ずつコピー（つづき 2）▶ ポインタを動かす

int*p, *q;for (p = a, q = b; p < a + 100; p ++, q += 2) {*q = *p;*(q + 1) = *p;}

15 / 21配列から配列へ各要素を 2 個ずつコピー（つづき 3）▶ ポインタを動かす（別解）int*p, *q;for (p = a, q = b; p < a + 100; p ++) {*q = *p;q ++;*q = *p;q ++;}16 / 21

配列から二つの配列へ交互にコピー▶ 添字を動かすinti;
for (i = 0; i < 50; i ++) {b[i] = a[i * 2];c[i] = a[i * 2 + 1];}▶ 添字を動かす（別解）
int
i, j;
for (i = 0, j = 0; j < 50; i += 2, j ++) {b[j] = a[i];c[j] = a[i + 1];}

17 / 21配列から二つの配列へ交互にコピー（つづき）▶ 添字を動かす（別解 2）
int
i, j;
for (i = 0, j = 0; j < 50; j ++) {b[j] = a[i];i ++;c[j] = a[i];i ++;}18 / 21配列から二つの配列へ交互にコピー（つづき 2）▶ ポインタを動かす
int*p, *q, *r;for (p = a, q = b, r = c; q < b + 50;
p += 2, q ++, r ++) {*q = *p;*r = *(p + 1);}

19 / 21配列から二つの配列へ交互にコピー（つづき 3）▶ ポインタを動かす（別解）int*p, *q, *r;for (p = a, q = b, r = c; q < b + 50;
q ++, r ++) {*q = *p;p ++;*r = *p;p ++;}20 / 21

まとめ
今回、学んだこと▶ C での配列とポインタの関係▶ ポインタに整数を足す・ポインタから整数を引く▶ ポインタからポインタを引く▶ ポインタとポインタの大小比較▶ 応用

21 / 21