C言語のポインタ演算と配列の関係を完全ガイド!初心者でもわかる仕組みと使い方
生徒
「C言語でポインタという言葉を見ましたが、全然意味がわかりません。配列と似ているように見えたり、違うように見えたりして難しいです。」
先生
「ポインタは、値そのものではなく、値が保存されている場所を示す仕組みなんだ。配列と関係が深いので、一緒に覚えると理解しやすいよ。」
生徒
「場所ってどういうことですか?配列は数字を順番に並べて使うものだと思っていました。」
先生
「配列は確かに数字や文字を並べたものだけれど、コンピュータの中では、データは全部メモリという長い部屋に保管されている。その部屋のどこに置いたかを指し示す番号がアドレスと呼ばれるものなんだ。」
1. ポインタとは?
C言語のポインタは、変数が保存されている場所の情報を持つ特別な変数である。変数は値を保存するが、ポインタは住所を保存する。住所とはメモリ上の位置のことであり、その位置を指定することで値を取り出したり書き換えたりできるようになる。この仕組みのおかげで、C言語はとても柔軟で効率的なプログラムを書くことができる。
2. 配列とポインタの深い関係
配列という言葉は、複数のデータをオレンジの箱のように横に並べた形として説明されることが多い。実際のコンピュータでも、配列の要素は連続したメモリに順番に並べて保存されている。そのため、一番最初の場所さえ分かれば、二つ目も三つ目も計算で求めることができる。この構造により、配列の先頭の住所がポインタとして扱われるという仕組みが成立している。
配列の名前をそのまま使うと、先頭要素のアドレスを意味する。つまり、配列の名前そのものがポインタのように動く場面がある。この特性は、アルゴリズムの処理やデータ操作で大きな力を発揮する。
3. ポインタ演算で配列を読み進める
ポインタは住所を持つ変数なので、その住所を足したり引いたりすることができる。この操作をポインタ演算と呼ぶ。例えば、配列の先頭のポインタがあれば、一つ先に進めることで次の要素にアクセスできるようになる。このとき単に一を足すのではなく、要素のサイズに応じて自動的に正しい距離だけ進むように設計されている。
#include <stdio.h>
int main(void)
{
int a[3] = {10,20,30};
int *p = a;
printf("%d\n", *p);
p++;
printf("%d\n", *p);
return 0;
}
10
20
この例では、配列の先頭がポインタに渡されており、ポインタを一つ進めることで次の要素にたどり着いている。記号が難しく見えるが、仕組みとしては本のページを一枚めくるようなイメージである。
4. ポインタと配列の違い
配列は最初に用意した箱の集まりであり、サイズを変えることはできない。一方、ポインタは住所を保存しているだけなので、移動したり違う配列を指すことができる。この違いを理解することで、データの受け渡しや関数の処理がとても柔軟になる。ただし、存在しない場所を指してしまうとプログラムが壊れるので、安全な扱いが必要になる。
5. 添字とポインタは同じ意味になる
配列の二番目の要素を読みたいときは添字を使う。添字とはa[1]のようにかっこを付けた表記であり、直感的にわかりやすい。実はこの書き方はポインタの計算と同じ結果になっている。先頭の住所を基準に、要素のサイズ分だけ移動して値を読むという仕組みが裏で動いている。つまり、a[1]は*(a + 1)と同じ意味になる。
6. アドレス演算子で配列を扱う
アドレス演算子とは、変数の住所を取り出すための記号である。配列の要素に使うと、その場所の住所が手に入る。住所が手に入れば、そこからポインタとして考えることができ、別の変数に保存したり関数に渡したりできるようになる。この仕組みは、配列の情報を効率的に扱うために欠かせない知識になる。
#include <stdio.h>
int main(void)
{
int a[3] = {5,6,7};
int *p = &a[0];
printf("%d\n", *p);
return 0;
}
5
この例では、先頭の住所を取り出してポインタに保存している。ポインタを使うことで、別の処理から同じ配列の要素にアクセスできるようになる。
7. ポインタ演算で繰り返し処理
配列の中身を順番に読むとき、ポインタを使って少しずつ進む方法がある。添字と違って、計算による処理になるので、高速に動くという利点がある。組込みや低レベルの処理でよく使われる手法であり、効率を求められる現場で役立つ考え方になる。
#include <stdio.h>
int main(void)
{
int a[3] = {2,4,6};
int *p = a;
for(int i=0;i<3;i++)
{
printf("%d\n", *p);
p++;
}
return 0;
}
2
4
6
このように、ポインタは配列の処理と非常に相性がよく、現場では基本的な技術として扱われている。