C言語入門|C文字列のルール:ヌル終端という絶対条件

ここまでで、
C言語の文字列が「char 配列である」こと、
そして「文字コード 0 が終わりの合図になる」ことを学びました。

でも実は、これらは単なる仕様説明ではありません。
C言語の世界では、**明文化されていなくても必ず守られている“業界ルール”**として扱われています。

これを知らずに文字列を扱うと、

  • 表示が途中で切れる。
  • 意味不明な文字が出る。
  • オーバーランで暴走する。

といった事故が、いとも簡単に起きてしまいます。

ここでは、C文字列に関する絶対に破ってはいけないルールを、あらためて整理していきましょう。

C言語の文字列に存在する「業界ルール」

C言語には、
「これは文字列です」と宣言する特別な型はありません。

それでも、文字列が文字列として正しく扱われるのは、
全員が同じ約束を守っているからです。

その約束が、次の2つです。

第1条:先頭から順に文字コードを並べる

文字列は、次のように表現されます。

  • 先頭要素から
  • 1文字ずつ
  • 文字コードを並べて格納する

たとえば、hello という文字列は、

'h' 'e' 'l' 'l' 'o'

という 文字コードの並び で表されます。

ここまでは、
配列として考えれば自然ですね。

第2条:最後に必ず「文字コード0」を置く

ここが、最重要ポイントです。

文字列として扱うためには、

最後の文字の直後に、文字コード 0 を必ず置く

という約束があります。

この「文字コード 0 の文字」を、

  • 終端文字
  • ヌル文字

と呼びます。

ソースコード上では、
エスケープシーケンスを使って

\0

と記述します。

ヌル終端がなぜ「絶対条件」なのか

C言語の文字列は、

  • 長さ情報を持たない
  • 何文字あるかを覚えていない

という特徴があります。

では、
どこまでが文字列なのかを、どうやって判断しているのでしょうか。

答えはひとつです。

最初に見つかった \0 まで

これだけが、
文字列の終わりを判断する唯一の手がかりなのです。

printf は何をしているのか

printf における書式指定子 %s は、

  • 渡された char 配列の先頭から
  • 1文字ずつ読み進め
  • \0 に到達したら表示を止める

という動作をします。

つまり、

printf は \0 を無視しているのではない
\0 より後ろを「文字列ではない」と判断している

ということです。

サンプルで確認してみよう

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

サンプルプログラム

プロジェクト名:11-3-1 ソースファイル名: sample11-3-1.c

#include <stdio.h>

typedef char String[16];

int main(void)
{
    String msg = "hello";
    printf("%s\n", msg);
    return 0;
}

この msg のメモリ上のイメージは、次のようになります。

'h' 'e' 'l' 'l' 'o' '\0' ? ? ? ...

printf は、

  • h e l l o を表示し
  • \0 を見つけた瞬間に
  • 「ここで終了」と判断

しているわけです。

ヌル文字が途中にあったらどうなる?

では、こんな文字列を考えてみましょう。

String msg = "he\0llo";

一見すると、
hello に見えますよね。

でも、実際のメモリ配置はこうなります。

'h' 'e' '\0' 'l' 'l' 'o' '\0'

実行結果

he

なぜなら、

  • 最初の \0 が
  • 「文字列の終わり」として扱われる

からです。

その後ろに何が書かれていようと、
文字列としては存在しないのです。

ヌル終端を壊すと何が起きるか

もし、

  • \0 を書き忘れた。
  • \0 を上書きしてしまった。

場合、どうなるでしょうか。

printf や文字列関数は、

  • \0 を探し続け
  • 配列の範囲を越えて
  • メモリの奥まで読み進める。

ことになります。

これはまさに、
第10章で学んだ オーバーラン です。

C文字列の怖さと美しさ

この仕組みは、

  • 非常にシンプル
  • 余計な情報を持たない。
  • 高速に動作する。

という、美しさを持っています。

一方で、

  • ルールを1つ破った瞬間
  • 一切の安全装置がなくなる

という、C言語らしい厳しさも併せ持っています。

ここで必ず覚えてほしいこと

この節で、絶対に持ち帰ってほしい結論はこれです。

C文字列は
ヌル終端されていて
はじめて文字列として成立する

ヌル終端は「あると便利」なものではありません。
存在しなければならない絶対条件です。

次の記事へ

次は、

  • ヌル終端はいつ自動で入るのか
  • どんな操作がヌル終端を壊すのか
  • 文字列操作関数がなぜ危険なのか

を、具体例とともに見ていきます。

ここを理解できれば、
C言語の文字列操作は
「怖いもの」から「扱える道具」に変わります。