C言語基礎|C言語の文字列

「見えない終端が“文字列”を支える――C言語の文字列はナル文字から始まる!」

C言語の文字列は“箱の行列”として理解すると一気にラクになる

前章で「文字は1つの値(文字コード)として扱う」ことを学びましたよね。
でも実際のプログラムで扱うのは、名前・文章・パスなど、複数の文字の並びがほとんどです。

C言語の文字列は、ざっくり言うと

  • 文字(char)がズラッと並ぶ。
  • そして最後に「終わり」を示す ナル文字(値0) が必ず付く。

という仕組みでできています。
この“見えない終端(ナル文字)”を理解すると、文字列のサイズ、表示、扱い方がスッとつながりますよ。

文字列とは:C言語では「ナル文字で終わる文字の並び」

1 文字・文字列・ナル文字の関係

用語意味
文字A1文字(char 1個ぶん)
文字列(概念)ABC文字が連なったもの
文字列(Cでの実体)A B C 0**最後に値0(ナル文字)**が付いた並び
ナル文字0 / \0値が0の文字。文字列の終端を表す

表の説明
C言語の文字列は「どこまでが文字列か」を、長さではなく 終端のナル文字で判断します。だから、最後の 0 が超重要なんです。

文字列リテラル:二重引用符で書くと“末尾にナル文字が付く”

たとえば "ABC" のように、二重引用符で囲んだものを 文字列リテラルと呼びます。

ポイントはこれです。

  • 見た目は3文字(A, B, C)
  • でも内部には 最後に 0(ナル文字) が追加される
  • なので、必要な箱(要素数)は 3 + 1 = 4

図で理解:文字列リテラルは「箱(char)の列」

文字列リテラルの内部イメージ

図の説明
"" は「0文字の文字列」ですが、C言語の文字列として成立させるために 終端の0だけは必須なので、箱が1個になります。

文字列リテラルの大きさ:sizeof は“終端のナル文字も含めたバイト数”

ここが気持ちいいポイントです。
sizeof(文字列リテラル) は、末尾のナル文字まで含んだサイズになります。

サンプルプログラム

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

// 文字列リテラルの大きさを確認する

#include <stdio.h>

int main(void)
{
    printf("サイズ確認:\n");
    printf("sizeof(\"Hi\")        = %zu\n", sizeof("Hi"));
    printf("sizeof(\"A\\nB\")      = %zu\n", sizeof("A\nB"));
    printf("sizeof(\"cat\\0dog\")  = %zu\n", sizeof("cat\0dog"));

    return 0;
}

想定される結果の読み方(例)

  • "Hi" は H, i, 0 の 3個分
  • "A\nB" は A, 改行, B, 0 の 4個分(\n は見た目2文字でも中身は1文字)
  • "cat\0dog" は c,a,t,0,d,o,g,0 の 8個分(途中の0とは別に末尾にも0が付く)

なぜ \n や \t が1文字扱いになるの?

エスケープシーケンスは“1文字を表す表記”

表記見た目中身(扱い)
\n2文字っぽい改行という 1文字
\t2文字っぽいタブという 1文字
\02文字っぽい値0の 1文字(ナル文字)

表の説明
エスケープシーケンスは「書き方は2文字以上」でも、実体は1文字としてメモリに入ります。だから sizeof にもそのまま反映されます。

途中に \0 があるとどうなる?

途中に \0(値0)が入っても、文字列リテラルそのもののメモリ上の並びは続きます。
ただし、C言語の多くの文字列処理(表示など)は 最初に出てきた0で“終わり”とみなすので、扱いに注意が必要です。

"cat\0dog" の内部イメージ

┌───┬───┬───┬───┬───┬───┬───┬───┐
│ c │ a │ t │  0 │ d │ o │ g │  0 │  ← 末尾にも0が付く
└───┴───┴───┴───┴───┴───┴───┴───┘

図の説明
「途中の0」は“文字列としての終端”として解釈されやすい一方で、メモリ上は後ろも存在します。ここがCの文字列のクセであり、面白いところです。

登場した命令・演算子の書式と役割

sizeof 演算子

  • 書式
    sizeof(式)
    sizeof(型)
  • 何をする?
    対象が占有する バイト数を返します。文字列リテラルの場合は 末尾のナル文字込みになります。

printf 関数

  • 書式(代表)
    int printf(const char *format, ...);
  • 何をする?
    書式付きで標準出力へ表示します。%zu は size_t(sizeofの結果)を表示するのによく使います。

include(ヘッダの取り込み)

  • 書式
    #include <stdio.h>
  • 何をする?
    printf などの入出力関数の宣言を利用できるようにします。