第32回 | C言語の配列とポインタが、同じ景色に見える瞬間|データと関数をつなぐ仕組み

* 当サイトでは、コンテンツの一部に広告を掲載しています。

System Note $ cat /proc/ai-disclosure

本記事の構成および論理分析にはAI(人工知能)を使用しています。情報の正確性は、システム管理者(UNIXユーザー)による手動検証済みです。

C言語の配列とポインタが、同じ景色に見える瞬間

はじめてのC言語 | 第32回

目次

配列とポインタは、どこでつながるのか

C言語では、配列や文字列を扱うとき、
「場所(ロケーション)」という考え方が、何度も顔を出します。

配列は「並んだ箱」。
ポインタは「箱の場所を指す札」。

最初は、まったく別の道具のように見えるこの2つですが、
あるところから、同じ並びを、別の見方で扱っていることに気づきます。

この回では、その瞬間を、ゆっくり確認していきましょう。

配列は、連続した場所に並んでいる

まずは、配列を思い出します。

int a[4] = {10, 20, 30, 40};

これは、

  • 箱が4つ、横に並び
  • 左から順に値が入っている

状態でした。

イメージすると、こんな並びです。

+----+----+----+----+
| 10 | 20 | 30 | 40 |
+----+----+----+----+

ここで、ひとつ大切なポイントがあります。

配列名 a は、先頭要素への入口として使われる

配列 a そのものは、
箱4つ分の実体を持っています。

つまり、
4つの int が連続して置かれているということです。

ただし、多くの式の中で名前 a を使うと、
a はこう振る舞います。

「私は、ここ(先頭)から始まっていますよ」

つまり配列名は、多くの場面で、
並びの入口を示す看板(先頭要素のアドレス)として使われるのです。

ただし、配列そのものがポインタに変わるわけではありません。
sizeof(a) のように、配列全体として扱われる場面もあります。

カフェのバックヤードで言えば、

  • 棚そのものを丸ごと動かすのではなく
  • この棚は、ここから始まっています

という札を使っている状態です。

「1つ右へ進む」という感覚

配列が「並んだ箱」だとすると、
そこには自然な流れがあります。

  • 先頭
  • その右
  • さらに右

ポインタを使うと、この流れをそのまま表現できます。

int *p = a;

これは、

  • 配列の先頭要素の場所を
  • ポインタ p が指している

という意味です。

ここで重要なのは、p は配列そのものではなく、
配列の先頭要素を指すポインタだという点です。

ここで、

p++;

と書くと、

  • 値が増えるのではなく
  • 指している場所が、ひとつ右へ進む

という動きになります。

箱は動いていません。
動いているのは、ロケーション札(p)だけです。

このとき p は、先頭の a[0] ではなく、
次の箱である a[1] を指すようになります。

ポインタを進めるときは、同じ配列の範囲内で考える必要があります。
配列の外を指すポインタから値を読んだり書いたりしてはいけません。

配列で見ていた景色

配列では、こんな書き方をしていました。

a[0]
a[1]
a[2]

これは、

  • 先頭の箱
  • その次の箱
  • さらに次の箱

を、番号で指定して見ています。

配列は、「何番目の箱か」という視点で世界を見ています。

ポインタで見ていた景色

一方、ポインタではこう書けます。
ここでは p++ の例とは切り分けて、p が a[0] を指しているものとして見ます。

*p
*(p + 1)
*(p + 2)

こちらは、

  • 今いる場所
  • そこから1つ右
  • さらに1つ右

と、場所をたどって見ています。

添字としての番号ではなく、
「今いる場所から、いくつ分進むか」という感覚で見ています。

同じ場所を、違う言葉で見ていただけ

ここで、ひとつの気づきが生まれます。

a[1]

*(p + 1)

この2つは、p が a[0] を指している場合、
同じ箱を指しています。

どちらも、同じ配列の中にある 20 の箱を見ています。
違うのは、そこへたどり着く書き方です。

  • 配列:番号で見る
  • ポインタ:場所から進んで見る

別々の道具に見えていたものが、
同じ連続したメモリを、別の書き方で見ていたわけです。

これが、「配列とポインタが、同じ景色に見える瞬間」です。

なぜ、別々のものに見えてしまうのか

初心者のころは、

  • 配列は [ ]
  • ポインタは * や +

と、記号がまったく違って見えます。

そのため、「配列とポインタは別の仕組みだ」と感じてしまいます。

でも、要素をたどる場面では、よく似た考え方をしています。

  • 連続した場所が並び
  • 先頭を基準に
  • どれだけ進むか

この世界を、

  • 配列は「番号」で
  • ポインタは「移動」で

表現していた、と考えると整理しやすくなります。

文字列でも、同じ景色を見る

文字列でも、同じ考え方がよく出てきます。

char s[] = "ABC";

中身は、

'A' 'B' 'C' '\0'

という、並んだ箱です。

だから、こんなコードが自然に書けます。

char *p = s;

while (*p != '\0') {
    p++;
}

これは、

  • 先頭の場所から始めて
  • ひとつずつ右へ進み
  • 終わりの印(\0)まで歩く

という処理です。

配列を番号で見るか、ポインタで歩くか。

どちらも、連続した文字の並びを順番に見ている点は同じです。

この感覚があると、何が変わるか

この「同じ景色」が見えるようになると、

  • for文の意味が見える
  • 文字列操作の理由が分かる
  • 関数に配列を渡す意味が分かる
  • 「なぜ危険なのか」を予測できる

ようになります。

C言語が、記号の集まりではなく、場所を扱う言葉に見えてきます。

まとめ

  • 配列とポインタは、同じものではない
  • ただし、配列名は多くの式で先頭要素へのポインタとして扱われる
  • 配列は「番号で見る」
  • ポインタは「場所からたどる」
  • 同じ連続した並びを、違う書き方で見ることができる

このことに気づいたとき、C言語の中が、少し静かに整理されます。

次は、「なぜ配列を関数に渡すと、姿が変わるのか」
その不思議を、同じ景色から見ていきましょう ☕

次回予告

次回は、配列を関数に渡したときに何が起きるのかを見ていきます。
配列とポインタの関係が分かると、sizeof の結果や、関数内で配列を書き換えたときの動きも自然に理解できます。

復習してみよう

復習したい方は、こちらもあわせてご覧ください。

用途ごとに選ぶ C言語のおすすめ本

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

のいのアバター のい UNIX Cafe マスター

Macintosh Color Classicから始まった旅は、長いWindows時代を経て、Windows10のサポート終了をきっかけにUNIXの世界へ戻ってきました。UNIX Cafeでは、UNIX・Linux・そしてMacな世界を、むずかしい言葉を使わず、物語のように書いています。プログラミングは、アイデアをコンピューターに伝えるための言葉です。簡単な単語と文法を覚えれば、誰でもコマンドを使えます。ぜひ一度、やさしいプログラミングの世界をのぞいてみてください。

Created by UNIX Cafe

目次