
C言語入門|文字列のためのメモリ確保方法
ここまでで、私たちは C言語の文字列について、かなり深いところまで理解してきました。
- 文字列の正体は char 配列であること
- 文字列の終わりは \0 で決まること
- 文字列は先頭アドレスでやり取りされること
このあたりは、もう「なるほど」と腹落ちしてきた頃でしょう。
ところが、ここで1つ気になるポイントが出てきます。
それが、文字列の業界ルール第4条 です。

業界ルール第4条の意味
文字列に関する業界ルールの第4条は、こう定めています。
配列を複製するメモリ領域を確保する手段は問わない。
一見すると、少しあいまいな表現に見えますね。
でも、これが意味しているのは、実はとても重要なことです。
文字列として扱えるかどうかは、
char 配列かどうかでは決まらない
という考え方です。
文字列に必要なのは「連続したメモリ」
C言語において「文字列」として扱われるために必要な条件は、とてもシンプルです。
- char が1文字ずつ順に並んでいる。
- 最後に \0 が置かれている。
- その先頭アドレスを管理できる。
この条件さえ満たしていれば、
どこに確保されたメモリであっても文字列として扱える
というのが、業界ルール第4条の本質です。
つまり、
文字列とは「データの並び方」であって
「確保方法」そのものではない
というわけです。
文字列のためのメモリ確保は3通りある
文字列を格納するための連続したメモリ空間を確保する方法は、実は大きく分けて次の3つしかありません。
| 手段 | 確保方法 | 確保される領域 |
|---|---|---|
| 手段① | 配列宣言 | スタック領域 |
| 手段② | malloc | ヒープ領域 |
| 手段③ | 文字列リテラル | 静的領域 |
この3つは、すべて文字列を実現できる という点では共通しています。
違うのは、「どこに」「どんな寿命で」確保されるかです。
配列宣言による文字列(スタック領域)
もっともなじみ深いのが、配列宣言による方法です。
char array[1024] = "C";
char* msg = array;この方法では、
- メモリはスタック領域に確保される。
- 関数が終了すると寿命が尽きる。
という特徴があります。
手軽で安全に見えますが、
「関数の外に持ち出せない」という制約がある点には注意が必要です。
malloc による文字列(ヒープ領域)
次に、第10章で学んだ malloc を使う方法です。
char* msg = (char*)malloc(1024);
msg[0] = 'C';
msg[1] = '\0';この方法では、
- メモリはヒープ領域に確保される。
- 関数が終了しても寿命は尽きない。
- free を忘れるとメモリリークになる。
という特徴があります。
柔軟で強力ですが、
管理責任がプログラマにある という点が最大のポイントです。
文字列リテラルによる文字列(静的領域)
そして3つ目が、少し意外に感じるかもしれない方法です。
const char* msg = "C";これは見た目こそ「ただの文字」ですが、
実際には メモリ確保が行われています。
プログラム起動時に、
- ソースコード中の文字列リテラル
- 書式文字列("%s" など)
はすべて 静的領域 に読み込まれます。
msg には、その静的領域にある
文字列 "C" の先頭アドレスが入っている、というわけです。
なぜ const char* なのか
文字列リテラルを指すポインタには、通常 const char* が使われます。
理由はとても現実的です。
- 静的領域は読み込み専用になる場合がある。
- 書き換えようとすると実行時エラーになる可能性がある。
そのため、
書き換えてはいけないメモリを指している
という意思表示として、const が付けられます。
C言語では警告で済む処理系もありますが、
C++ では非推奨となるため、
リテラルを指すポインタには const を付ける
というのが現在の安全な文化です。
同じ「文字列」でも性質はまったく違う
ここまでをまとめると、次のようになります。
| 変数 | 実体 | 寿命 | 解放 |
|---|---|---|---|
| msg1 | スタック上の配列 | 関数終了まで | 自動 |
| msg2 | ヒープ領域 | free まで | 手動 |
| msg3 | 静的領域 | プログラム終了まで | 不要 |
見た目はどれも char* で扱える「文字列」ですが、
裏側の性質はまったく別物 です。
ここからが本番
この違いを理解せずに文字列を扱うと、
- 寿命切れのメモリを参照する。
- 書き換えてはいけない領域を書き換える。
- free し忘れてメモリリークする。
といった事故につながります。
逆に言えば、
どの領域に、どの方法で文字列を確保しているか
を意識できるようになると、
C言語の文字列操作は一気に見通しがよくなります。
