C言語入門|文字列は先頭アドレスで渡す

ここまでで、私たちは C言語における文字列の正体をかなり深く理解してきました。

  • 文字列の実体は char 配列であること
  • 文字列の終わりは \0 で決まること
  • \0 以降のメモリは「文字列ではない」こと

これらを理解したことで、
「なぜ C言語の文字列は扱いが独特なのか」
その理由が、だんだん見えてきたのではないでしょうか。

そしてここで、もう1つ重要な 業界ルールの続き を知る必要があります。

C言語の文字列に関する業界ルール

C言語の世界では、文字列を扱う際に次のルールが暗黙の前提として共有されています。

条文内容
第1条先頭要素から順に1文字ずつ文字コードを格納して文字列を表す。
第2条最後の文字の直後に文字コード0を置き、以降は無視する。
第3条文字列を関数などに渡す場合は、先頭文字のアドレスだけを渡す。
暗黙条配列を複製する方法は問わない。

今回の主役は、この 第3条 です。

なぜ「先頭アドレスだけ」でいいのか

たとえば、500文字からなる長い文字列があるとします。
先頭アドレスは仮に 8000 番地としましょう。

この文字列を printf で表示したい場合、
本当に 500文字分すべての情報を渡す必要があるでしょうか?

答えは NO です。

printf は、

  1. 渡されたアドレスから読み始め
  2. 次の文字、さらに次の文字と順にたどり
  3. \0 に到達したら処理を終える

という動きをします。

つまり、

先頭文字のアドレスさえ渡せば
あとは printf が勝手に最後まで読んでくれる

これが、第3条の考え方です。

printf と文字列の受け渡しの正体

私たちはこれまで、何気なく次のようなコードを書いてきました。

char str[1024] = "hello";
printf("%s", str);

一見すると、「str に入っている文字列そのもの」を
printf に渡しているように見えます。

しかし、配列変数名が式の中に書かれると

それは、

先頭要素のアドレスに化ける

のでした。

つまりこのコードは、実際には次の意味になります。

printf("%s", &str[0]);

最初から最後まで、
文字列の先頭アドレスしか渡していなかった のです。

業界ルールが支えている仕組み

ここで重要なのは、

  • 第1条:順番に文字が並んでいる。
  • 第2条:\0 で終わる。

というルールがあるからこそ、

  • 第3条:先頭アドレスだけ渡せばよい

という仕組みが成立している、という点です。

もし \0 が存在しなければ、
printf は「どこまで表示すればいいのか」分からなくなってしまいます。

C言語における文字列管理の考え方

この文化をひとことで表すと、こうなります。

長い文字列でも、
先頭アドレスだけを管理し、やり取りに使う
(末尾は \0 によって自動的に分かる)

これが、C言語における文字列管理の基本思想です。

「文字列」と「文字列を指すポインタ」の混同

ここで、C言語特有の ややこしさ が登場します。

次のコードを見てください。

char str[1024] = "hello";
char* p = str;

printf("%s, %s\n", str, p);

このコードでは、str も p も、
どちらも同じように hello を表示します。

  • str は char 配列で、文字情報そのものを持っている
  • p は char* 型で、文字列の先頭アドレスを持っているだけ

にもかかわらず、
どちらも「文字列」として扱われてしまうのです。

なぜこんな呼び方がされるのか

本来の意味での「文字列」とは、

メモリ空間に並んだ文字情報そのもの

です。

しかし C言語の世界では、

文字列は先頭アドレスで管理する

という文化があまりにも定着しているため、

  • 文字列本体
  • 文字列の先頭アドレス

この両方をまとめて
文字列と呼ぶことが多い のです。

これが、C言語が「紛らわしい」と言われる大きな理由の1つでもあります。

ここまで理解できたら一段上

この節の内容が自然に理解できるようになったなら、
あなたはもう、

  • ポインタに振り回される初心者
  • 文字列が怖いCプログラマ

ではありません。

文字列を

  • メモリ
  • アドレス
  • \0

という視点で捉えられる、
C言語らしい思考 が身についてきています。

次のステップへ

次は、

  • 文字列を受け取る関数の書き方
  • char* 引数の意味
  • 書き換え可能な文字列とそうでない文字列

といった話に進んでいきます。

「文字列は先頭アドレスで渡す」
この考え方が、これから何度も登場することになるでしょう。