配列は、データがメモリ上に順に並んでいるので、ポインタと相性がいい。前のエントリでさらっと書いたけど、配列名を添字を付けずに使うと、先頭を指すポインタを返す。
int a[10];
int *p;
p = a;
配列の要素にポインタでアクセス
配列の各要素には、添字を使ってアクセスするほかにポインタを使ってもアクセスできる。
#include
int main(void)
{
int a[10] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int *p;
p = a;
printf("%d %d %d\n", a[0], a[1], a[2]); /* access with index */
printf("%d %d %d\n", *p, *(p + 1), *(p + 2)); /* access with pointer */
return 0;
}
takatoh@nightschool $ ./sample_6_3a
10 20 30
10 20 30
2次元配列
2次元配列の場合は、ポインタを型キャストしてやる必要がある。これはよくわからないな。次のような float 型の2次元配列の要素にアクセスするには、float 型のポインタでいいんじゃなかろうか。
#include
int main(void)
{
float balance[5][5] = {
{ 1.0, 2.0, 3.0, 4.0, 5.0},
{ 6.0, 7.0, 8.0, 9.0, 10.0},
{11.0, 12.0, 13.0, 14.0, 15.0},
{16.0, 17.0, 18.0, 19.0, 20.0},
{21.0, 22.0, 23.0, 24.0, 25.0}
};
float *p;
p = balance;
printf("%f\n", *p);
printf("%f\n", *(p + 1));
return 0;
}
これを試してみると:
takatoh@nightschool $ gcc sample_6_3b.c -o sample_6_3b
sample_6_3b.c: In function ‘main’:
sample_6_3b.c:15:3: warning: assignment from incompatible pointer type [enabled by default]
p = balance;
^
takatoh@nightschool $ ./sample_6_3b
1.000000
2.000000
出力結果は予想どおりだけど、コンパイル時に warning が出ている。互換性のないポインタを代入している、ということらしい。でもちゃんと動いてるんだけど…。
ポインタへの代入を次のように直すと warning は出なくなった。
#include
int main(void)
{
float balance[5][5] = {
{ 1.0, 2.0, 3.0, 4.0, 5.0},
{ 6.0, 7.0, 8.0, 9.0, 10.0},
{11.0, 12.0, 13.0, 14.0, 15.0},
{16.0, 17.0, 18.0, 19.0, 20.0},
{21.0, 22.0, 23.0, 24.0, 25.0}
};
float *p;
p = (float *) balance;
printf("%f\n", *p);
printf("%f\n", *(p + 1));
return 0;
}
takatoh@nightschool $ gcc sample_6_3c.c -o sample_6_3c
takatoh@nightschool $ ./sample_6_3c
1.000000
2.000000
ポインタの添字
ポインタが配列を指しているときに限って、ポインタに添字をつけることができる。
#include
int main(void)
{
char str[] = "Pointer is interesting.";
char *p;
int i;
p = str;
for (i = 0; p[i]; i++) {
printf("%c", p[i]);
}
printf("\n");
return 0;
}
takatoh@nightschool $ ./sample_6_3d
Pointer is interesting.
配列のアドレスを使う
最初に書いたように、配列名を添字を付けずに書くとその配列の先頭を指すポインタを返す。なのでこれを普通のポインタの代わりに使うこともできる。
#include
int main(void)
{
char str[80];
*(str + 3) = 'c';
printf("%c\n", *(str + 3));
return 0;
}
takatoh@nightschool $ ./sample_6_3e
c
[追記]
コメントをもらった。配列名を添字なしで使ったときにポインタのように振る舞うのは、暗黙の型変換が行われるからだそう。配列名の型自体はあくまで配列だと。
ふーむ、なるほど。でも、参照するときに限って言えば、暗黙の型変換のおかげで実質的にポインタとして(というかポインタの代わりに)使えるってことでいいのかな。