C言語の文字列とは?char配列・終端文字・文字列リテラルを分かりやすく解説

目次

はじめに

C言語を学び始めると、こんなコードが出てきます。

C
char str[] = "hello";

なんとなく「文字列」っぽいことは分かっても、

初心者さん

文字列って何?\0 って何?

初心者さん

string型じゃないの?なぜ char を使うの?

初心者さん

配列なの?ポインタなの?

と混乱しやすいポイントでもあります。

実際、C言語の文字列は他言語とかなり考え方が違います。

この記事では、

  • C言語の文字列の正体
  • \0(終端文字)の意味
  • char配列との関係
  • 文字列リテラルとは何か
  • 初心者がハマりやすい注意点

を実務目線で分かりやすく解説します。


C言語文法解説シリーズ

本記事は「C言語文法解説シリーズ」の1つです。
C言語の文法を、組み込み開発の視点も交えて解説しています。

C言語文法解説シリーズ一覧はこちら

C言語の文法を基礎から体系的に解説するシリーズです。

配列やポインタがまだ曖昧な方は、先にこちらもおすすめです。

👉 「配列とは?」
👉 「ポインタとは?」


文字列とは?

まず結論から言うと、

👉 C言語に「string型」はありません。

C言語では、

C
char str[] = "hello";

のように、

👉 「char配列」で文字列を表現します。


初心者さん

えっ、文字列って専用の型じゃないんですか?

エンジニアくん

C言語では違うんだ。文字を並べた char配列 を文字列として扱っているんだよ


char型についてはこちらの記事で解説しています。

文字列の内部構造

例えば、

C
char str[] = "hello";

は内部的にはこうなっています。

C
{'h', 'e', 'l', 'l', 'o', '\0'}

つまり、

C
+---+---+---+---+---+---+
| h | e | l | l | o |\0 |
+---+---+---+---+---+---+

のように、1文字ずつメモリに並んでいます。

ここで重要なのが最後の \0 です。


文字は内部では数値で管理されている

実はコンピュータは、

👉 「文字」をそのまま保存しているわけではありません。

内部では、

'A' → 65
'B' → 66

のように、

👉 「文字コード」という数値で管理しています。

これを理解すると、

  • 文字列
  • char型
  • UTF-8
  • 日本語文字化け

などの理解にもつながります。

詳しくはこちら:

\0(終端文字)とは?

\0 は「文字列の終わり」を表す特殊な文字です。

これを「終端文字(NULL文字)」と呼びます。


なぜ \0 が必要なのか

C言語の文字列は、

👉 「長さ情報」を持っていません。

つまり、

C
char str[] = "hello";

を見ても、CPUや関数は、

  • 5文字なのか
  • 20文字なのか

を分からないのです。

そこで、

\0 が出るまでを文字列とする

というルールになっています。


printf(“%s”) が動く理由

例えば、

C
printf("%s", str);

は内部的に、

\0 が出るまで1文字ずつ表示する

という処理をしています。


初心者さん

なるほど… \0 があるから文字列の終わりが分かるんですね

エンジニアくん

そう。C言語では \0 が超重要なんだ


\0 が無いとどうなる?

例えば、

C
char str[5] = {'h', 'e', 'l', 'l', 'o'};

これは一見正しそうですが、

👉 \0 が存在しません。

そのため、

C
printf("%s", str);

を実行すると、

👉 メモリ上を暴走してしまう可能性があります。

これは非常に危険です。


文字列は char配列

文字列は実体としては char配列なので、

C
str[0] = 'H';

のように、配列アクセスできます。

実行結果:

Hello

になります。


配列だから連続したメモリに並ぶ

例えば:

C
char str[] = "abc";

はイメージ的にはこうです。

1文字ずつ連続して並びます。

この考え方はポインタ理解にも直結します。

配列とポインタについてはこちら


文字列リテラルとは?

次に、よく出てくるこのコード。

C
char *str = "hello";

これは、

👉 "hello" という文字列リテラルをポインタで指しています。


char配列とは意味が違う

実はこの2つは違います。

C
char str1[] = "hello";
char *str2 = "hello";

配列版

C
char str1[] = "hello";

これは、

👉 配列の中に "hello" がコピーされます。

なので書き換え可能です。

C
str1[0] = 'H';

OKです。


ポインタ版

C
char *str2 = "hello";

こちらは、

👉 文字列リテラルを指しているだけです。

そのため、

C
str2[0] = 'H';

は危険です。

環境によってはクラッシュします。

char配列とポインタの違いについてはこちらの記事で詳しく解説しています。


なぜ危険なのか

文字列リテラルは、

👉 書き換え禁止領域(.rodata領域など)

に置かれることが多いためです。

組み込み開発では特に重要なポイントです。

.rodata領域についてはこちらの記事で解説しています。


実務では const を付けることが多い

実際には、

C
const char *str = "hello";

と書くことが多いです。

これなら、

👉 「書き換えない文字列ですよ」

という意図を明確にできます。

constの使い方についてはこちらの記事で解説しています。


sizeof と strlen の違い

初心者が混乱しやすいポイントです。

C
char str[] = "hello";

に対して、

C
sizeof(str)

C
strlen(str)

は意味が違います。


sizeof

C
sizeof(str)

は配列サイズを取得します。

結果:

6

になります。

理由は \0 も含むためです。


strlen

C
strlen(str)

は文字列長を取得します。

結果:

5

になります。

こちらは \0 を含みません。


初心者さん

同じ5文字なのに結果が違うんですね…!

エンジニアくん

sizeof はメモリサイズ、strlen は文字数なんだ


詳しくは以下の記事で解説しています。


よくあるミス

配列サイズ不足

例えば:

C
char str[5] = "hello";

これは危険です。

"hello" は、

h e l l o \0

なので6バイト必要です。


文字列リテラルを書き換える

C
char *str = "hello";

str[0] = 'H';

これは未定義動作です。

実務でもバグ原因になりやすいポイントです。


まとめ

C言語には string型がありません。

文字列は、

👉 char配列 + \0

で表現されています。

今回のポイントを整理すると:

  • 文字列はchar配列
  • \0 が文字列終了を表す
  • printfは \0 を見て動く
  • 配列版とポインタ版は違う
  • 文字列リテラルの書き換えは危険

文字列理解は、

  • 配列
  • ポインタ
  • メモリ
  • const
  • rodata領域

など、多くの重要概念につながります。

次の記事では、さらに混乱しやすい

👉 「char配列とポインタの違い」

を詳しく解説します。

この記事が参考になった方へ

配列を含むC言語の基本文法をこちらの記事で整理しています。

エンジニアとして技術を学ぶことは重要ですが、
キャリアや副業についても同時に考える必要があります。

副業の現実や市場価値、今後のキャリア戦略については、
こちらの記事でまとめています。

技術に関するご相談・開発・自動化ツール作成・記事執筆などのご依頼も承っています。

小さなご相談からでもお気軽にご連絡ください。

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

この記事を書いた人

組み込みソフトエンジニアとして働きながら、
C言語・メモリ・ポインタなどの基礎から実務まで解説しています。

副業・キャリアについても実体験ベースで発信中です。

X・Qiita・noteでも発信しています。
X:更新情報・日常
Qiita:技術発信
note:キャリア・副業

▼まずはここから読むのがおすすめ
C言語文法シリーズ
メモリ領域解説シリーズ
割り込み処理解説シリーズ
ソフトウェア設計解説シリーズ
キャリアと副業ロードマップ

コメント

コメントする


目次