はじめに
C言語の文字列には大きく分けて以下の3種類があります。
それぞれメモリ上の配置や取り扱いが異なるため、挙動の違いを理解しておきましょう。
- 文字列リテラル(文字列定数)
- 文字配列
- 文字列ポインタ
1. 文字列リテラル(文字列定数)
char *s = "Hello, World!";
- 定数(
const
相当) - プログラム実行中は変更不可
- コンパイラが用意する「静的領域(.rodataなど)」に配置
- 複数回同じリテラルが出現すると、1つの領域を共有することがある
2. 文字配列
char s[] = "Hello, World!";
- 実際には文字数+終端文字分の要素を持つ配列
- 変数と同様、スタック領域(関数内宣言の場合)やデータ領域(静的・グローバルの場合)に配置
- 要素を書き換え可能
- サイズは初期化時にしか決まらない
3. 文字列ポインタ
const char *p = /* 何らかの文字列 */ ;
- ポインタ変数(アドレスを保持)
- ポインタ自体はスタック上に配置され、中身はどこかの文字列領域を指す
- 指している先が文字列リテラルなのか、ヒープや配列なのかはコード次第
- 書き換え可能な領域を指していなければ、参照先の書き換えは未定義動作
まとめ
- 文字列リテラルは定数、文字配列は可変、ポインタは間接的に参照
- メモリ配置を意識して、安全かつ効率的なコードを書く
苦手意識のあるC言語の文字列周りも、メモリを意識するとグッと理解が深まります。ぜひ試してみてください!