トラック9・🔤文字列

文字列リテラルと初期化

読む目安 約12分・ゴール:文字列の初期化の書き方を使い分け、代入できない理由を説明できる

アプリでこのトピックを学ぶ(無料・登録不要)

このトピックの要点

ソースコードにダブルクォートで書いた "hello" を文字列リテラルと呼びます。文字列の初期化には、いくつかの書き方があります。

char a[6] = "hello";                              // 大きさを自分で指定
char b[] = "hello";                               // 大きさは自動で6になる
char c[20] = "hello";                             // 余裕を持たせる(残りは0)
char d[4] = {'c', 'a', 't', '\0'};                // 1文字ずつ並べる

b の書き方が便利です。文字数を数えなくても、コンパイラが '\0' のぶんを含めて大きさを決めてくれます。文字列を後から書き換える予定がないなら、これが最も安全です。

c のように大きく取るのは、あとで長い文字列を入れ直す予定があるときです。余った要素は 0 で埋まります。

代入はできない

初期化はできるのに、あとから代入はできません。

char s[10] = "hello";
s = "world";            // ← コンパイルエラー!

配列そのものへの代入がCでは許されていないからです(t08-05で見たとおりです)。文字列を入れ直したいときは、専用の関数 strcpy を使います。

#include <stdio.h>
#include <string.h>

int main(void)
{
    char s[10] = "hello";

    strcpy(s, "world");     // 中身を丸ごと入れ替える
    printf("%s\n", s);      // world
    return 0;
}

strcpy(コピー先, コピー元) の順番です。「代入と同じで左が行き先」と覚えると迷いません。ただしこの関数には大きな落とし穴があり、t09-05でたっぷり扱います。

比べるのも == ではできない

if (s == "world")       // ← これは中身を比べていない!

この書き方はコンパイルが通ることもありますが、文字列の中身を比較していません。中身を比べるには strcmp を使います。詳しくは次のトピックです。

どの書き方を選ぶか

書き換える予定がないなら char s[] = "..."、あとで入れ替えるなら大きめに取って char s[64] = "...";。この2つを押さえておけば十分です。よくある失敗は、char s[] = "hi";(大きさ3)に対して、あとから長い文字列を strcpy してしまうこと。宣言したときの文字数がそのまま上限になっているので、確実に溢れます。「あとで入れ替えるなら、最初から大きく取る」と覚えてください。

罠・注意

ビット初期化はOK、代入はNG。入れ直したいときは strcpy、と覚えよう

まとめ: 文字列の初期化は char s[] = "..." が基本。あとからの代入はできず、入れ直しは strcpy、比較は strcmp を使います。

アプリでこのトピックを学ぶ(無料・登録不要)

確認問題

確認問題 1

char s[] = "cat"; と宣言したとき、sizeof(s) はいくつになりますか。

  1. 3
  2. 4
  3. 5
  4. 環境によって変わる
答えを見る

正解:B(4)

'c' 'a' 't' の3文字に終わりの印 '\0' が加わるので4です。大きさを省略して書くと、コンパイラが '\0' のぶんまで数えて確保してくれます。strlen(s) のほうは3になります。

確認問題 2

文字列を入れ替えたいのですが、コンパイルエラーになります。原因の行はどれですか。

1#include <stdio.h>
2#include <string.h>
3
4int main(void)
5{
6    char s[10] = "hello";
7
8    s = "world";
9    printf("%s\n", s);
10    return 0;
11}
答えを見る

バグのある行:8行目

配列そのものへの代入はできません。8行目を strcpy(s, "world"); に直します。文字列を入れられるのは宣言と同時の初期化のときだけです。

char s[10] = "hello"; は初期化なので書けますが、あとから s = "world"; と代入することはできません。中身を入れ替えるには strcpy を使います。

「文字列」の目次

  1. 文字列とはchar配列である
  2. ヌル終端 '\0' の掟
  3. 文字列リテラルと初期化
  4. string.h の主要関数
  5. 安全な文字列操作——バッファサイズの意識
  6. 文字の判定と変換(ctype.h)
  7. 文字コードの基礎——ASCIIとUTF-8
  8. 文字列処理の定石パターン

もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。

完全版の販売ページは準備中です。

ほかのトラック

📚 姉妹教材:手を動かして覚える Linux 教材 — Linuxとインフラの仕組みを地図で学ぶ

Web版