C言語の基本|文字定数と文字列リテラルの違い

単一引用符は1文字、二重引用符は文字列。似ている表記の違いを知れば、C言語の文字処理が見えてくる。

C言語では、文字を扱うときに単一引用符と二重引用符を使います。

たとえば、次の2つは画面へ表示すると、どちらもAに見えます。

'A'
"A"

しかし、C言語ではまったく同じものではありません。

'A'は、1文字を表す文字定数です。

"A"は、文字Aと文字列の終わりを示すナル文字を並べた文字列リテラルです。

この違いを理解していないと、char型の変数へ値を入れる場面や、printfで%cと%sを使い分ける場面で混乱しやすくなります。

ここでは、次の内容を詳しく確認します。

  • 文字定数の基本的な書き方
  • 文字列リテラルの基本的な書き方
  • 単一引用符と二重引用符の違い
  • 文字列の終わりを示すナル文字
  • エスケープシーケンスの考え方
  • printfにおける%cと%sの使い分け
  • 空文字列の意味
  • 日本語を文字列として扱うときの注意点
  • 文字定数と文字列リテラルで起こりやすい間違い

今後、文字配列、ポインタ、文字列関数を学ぶときにも、この違いは大切な土台になります。

まずは、1文字なのか、文字の並びなのかという視点から整理していきましょう。

文字定数とは

文字定数は、基本的に1つの文字を表すための記述です。

C言語では、文字を単一引用符で囲みます。

'A'
'B'
'9'
'#'

たとえば、char型の変数gradeを文字Aで初期化する場合は、次のように書きます。

char grade = 'A';

このコードでは、'A'が文字定数です。gradeは、その値を保存するchar型の変数です。

文字定数の基本を整理すると、次のようになります。

項目内容
表すもの基本的に1文字
囲み方単一引用符
'A'、'9'、'#'、'\n'
主な保存先char型の変数
printfの変換指定%c

数字の7と文字の7は異なる

次の2つは、どちらも7と書かれていますが、意味が異なります。

7
'7'

7は整数定数です。

'7'は数字の形をした文字を表す文字定数です。

表記種類意味
7整数定数数値としての7
'7'文字定数文字としての7

整数定数の7は、計算に使用できます。

int result = 7 + 3;

文字定数の'7'は、画面へ数字の形をした文字として表示できます。

char digit = '7';

printf("%c\n", digit);

実行結果は次のようになります。

7

見た目が同じでも、数値と文字では用途が異なります。

文字定数は内部では数値として扱われる

コンピューターは、文字そのものを直接記憶しているわけではありません。文字と数値を対応させた文字コードを使って保存します。

たとえば、ASCIIと互換性のある環境では、大文字のAに数値65が対応しています。

char letter = 'A';

このとき、letterにはAに対応する数値が保存されます。printfで%cを使用すると、その数値に対応する文字Aが表示されます。

printf("%c\n", letter);

C言語では、'A'のような通常の文字定数の型はintです。ただし、文字コードの値として扱われるため、char型の変数へ代入して使用することがよくあります。

初心者の段階では、次のように理解しておけば大丈夫です。

  • 'A'は1文字を表す
  • char型の変数へ保存できる
  • %cで文字として表示できる
  • 内部では文字コードに対応する数値として扱われる

図1:文字定数と文字列リテラルの基本的な違い

この図から分かること

文字定数'A'は、単一引用符で囲まれた1文字です。char型の変数へ保存し、printfの%cで表示できます。

文字列リテラル"A"は、二重引用符で囲まれた文字の並びです。見えている文字はAだけですが、末尾には文字列の終了を示す\0が自動的に追加されます。

表示結果が同じAであっても、C言語の中での構造と使い方は異なります。

エスケープシーケンスも1文字を表す

文字定数には、画面上へそのまま書きにくい特殊な文字も指定できます。

そのために使うのがエスケープシーケンスです。

'\n'
'\t'
'\\'
'\''

たとえば、'\n'は改行を表す文字定数です。

ソースコード上ではバックスラッシュとnの2文字に見えますが、C言語では改行という1つの文字として扱われます。

よく使うエスケープシーケンスは、次のとおりです。

書き方意味
\n改行
\t水平タブ
\バックスラッシュ
\'単一引用符
\"二重引用符
\0ナル文字

改行をchar型の変数へ保存することもできます。

char new_line = '\n';

ただし、通常はprintfの文字列の中で使うことが多いでしょう。

printf("1行目\n2行目\n");

実行結果は次のようになります。

1行目
2行目

バックスラッシュを1文字として表す

バックスラッシュは、エスケープシーケンスの開始に使われる特別な文字です。

そのため、バックスラッシュそのものを文字定数として書く場合は、2つ続けます。

char backslash = '\\';

printfで%cを使うと、バックスラッシュが1文字表示されます。

printf("%c\n", backslash);

単一引用符を文字として表す

単一引用符は、文字定数を囲むために使います。

そのため、単一引用符そのものを文字として表す場合は、バックスラッシュを付けます。

char single_quote = '\'';

この場合、外側の単一引用符が文字定数の範囲を示し、中央の'が単一引用符という1文字を表します。

文字列リテラルとは

文字列リテラルは、0文字以上の文字の並びを表します。

C言語では、文字列を二重引用符で囲みます。

"ABC"
"computer"
"C language"
"こんにちは"

文字列リテラルは、printfで文章を表示するときに繰り返し使ってきました。

printf("C言語を学習しています。\n");

このコードでは、次の部分が文字列リテラルです。

"C言語を学習しています。\n"

文字列リテラルの基本を整理すると、次のようになります。

項目内容
表すもの0文字以上の文字の並び
囲み方二重引用符
"ABC"、"X"、""
終端自動的に\0が付く
printfの変換指定%s
主な用途メッセージ表示、文字列処理

1文字だけでも文字列にできる

文字列リテラルは、必ず複数の見える文字を含む必要はありません。

次の"A"も、有効な文字列リテラルです。

"A"

見えている文字はAだけですが、文字列の終わりを示す\0が追加されます。

概念的には、次のような並びです。

'A' '\0'

そのため、文字列リテラル"A"は、文字Aだけを表す文字定数'A'とは異なります。

空文字列も有効な文字列リテラル

文字列リテラルは、見える文字が1つもない状態でも作れます。

""

これを空文字列と呼びます。

空文字列には、表示する文字は入っていません。しかし、文字列の終わりを表す\0は存在します。

概念的には、次のようになります。

'\0'

空文字列をprintfの%sで表示しても、見える文字は表示されません。

printf("開始%s終了\n", "");

実行結果は次のようになります。

開始終了

文字列の最後にはナル文字が付く

C言語の文字列を理解するときに、特に重要なのがナル文字です。

ナル文字は、文字列の終わりを表す特別な文字で、\0と書きます。

たとえば、文字列リテラル"ABC"は、メモリ上では概念的に次のように並びます。

'A' 'B' 'C' '\0'

文字列処理を行う関数は、先頭から1文字ずつ確認し、\0が見つかった位置で文字列が終わったと判断します。

位置保存される文字
1'A'
2'B'
3'C'
4'\0'

見える文字は3文字ですが、終端の\0を含めると4文字分の領域が必要です。

ナル文字と数字の0は異なる

次の3つは、見た目が似ていますが意味が異なります。

0
'0'
'\0'
表記種類意味
0整数定数数値の0
'0'文字定数数字の形をした文字0
'\0'文字定数値0を持つナル文字

'0'は画面へ表示できる数字の文字です。

'\0'は文字列の終わりを表すために使われ、通常は見える形では表示されません。

この2つを混同しないようにしましょう。

図2:文字列ABCとナル文字の並び

この図から分かること

文字列リテラル"ABC"には、見えているA、B、Cの後ろにナル文字\0が自動的に付きます。

C言語には文字列専用の基本型があるわけではなく、文字を順番に並べ、最後に\0を置くことで文字列として扱います。

文字列処理では、この\0が終端を示す重要な役割を持っています。

sizeofで必要な領域の違いを確認できる

sizeofを使うと、文字定数と文字列リテラルの違いを別の角度から確認できます。

sizeof('A')
sizeof("A")
sizeof("ABC")
sizeof("")

C17では、通常の文字定数'A'の型はintです。そのため、sizeof('A')はsizeof(int)と同じになります。

一方、文字列リテラル"A"には、Aと\0が含まれます。

文字列リテラル"ABC"には、A、B、C、\0が含まれます。

基本実行文字集合の文字を使用した場合は、次のようになります。

表記内容sizeofの結果
"A"A、\02
"ABC"A、B、C、\04
""\01

文字列リテラルは、見える文字数に終端の\0を加えた大きさになります。

文字列リテラルは文字の配列

C言語では、文字列リテラルは文字が並んだ配列として扱われます。

たとえば、"ABC"は概念的には次の配列に対応します。

char text[] = { 'A', 'B', 'C', '\0' };

文字列リテラルを使うと、同じ内容を短く書けます。

char text[] = "ABC";

この場合も、配列textにはA、B、C、\0が格納されます。

text[0] = 'A'
text[1] = 'B'
text[2] = 'C'
text[3] = '\0'

配列の詳しい使い方は後の学習内容ですが、文字列は複数のchar型の値が並んだものだと考えると理解しやすくなります。

文字列リテラルそのものは変更しない

文字配列として作成したtextの要素は変更できます。

char text[] = "ABC";

text[0] = 'X';

この場合、textの内容はXBCになります。

一方、文字列リテラルそのものを変更しようとしてはいけません。

char *text = "ABC";

この形でtextが指している文字列リテラルを書き換えると、動作は保証されません。

ポインタの詳しい仕組みは後の学習内容ですが、今の段階では次のように覚えておきましょう。

  • 文字列リテラルは読み取り用として扱う
  • 内容を変更したい場合は文字配列として用意する
  • 文字列の終わりには\0が必要

文字定数と文字列リテラルを比較しよう

違いを表で整理すると、次のようになります。

比較項目文字定数文字列リテラル
'A'"A"
表すもの基本的に1文字0文字以上の文字の並び
囲み方単一引用符二重引用符
終端の\0自動では付かない自動的に付く
主な保存方法char型の変数char型の配列
printfでの表示%c%s
主な用途1文字の判定や保存メッセージや文字列処理

判断に迷ったときは、次のように考えると分かりやすくなります。

  • 1文字だけを扱うなら文字定数
  • 文字の並びを扱うなら文字列リテラル
  • 1文字に見えても文字列として扱うなら"A"
  • 改行などの1つの特殊文字には'\n'

プログラムで文字定数と文字列リテラルを確認しよう

次のプログラムでは、整数、小数、文字定数、文字列リテラルを使って、観測データを表示します。

観測データとメッセージを表示するプログラム

ファイル名:4_5_1.c

// 観測データとメッセージを表示するプログラム
#include <stdio.h>

int main(void)
{
    /* 整数定数を使って観測回数を初期化する */
    int observation_count = 8;

    /* 浮動小数点定数を使って気温を初期化する */
    double temperature = 21.7;

    /* 文字定数を使って判定記号を初期化する */
    char status = 'N';

    /* 整数を表示する */
    printf("観測回数:%d回\n", observation_count);

    /* 小数を表示する */
    printf("現在の気温:%.1f度\n", temperature);

    /* 文字定数から保存した1文字を表示する */
    printf("判定記号:%c\n", status);

    /* 文字列リテラルを%sへ渡して表示する */
    printf("観測メッセージ:%s\n", "現在の状態は正常です");

    return 0;
}
実行結果の例
観測回数:8回
現在の気温:21.7度
判定記号:N
観測メッセージ:現在の状態は正常です

このプログラムでは、文字定数'N'をchar型の変数statusへ保存しています。

一方、"現在の状態は正常です"は文字列リテラルとして、printfの%sへ直接渡しています。

整数定数の使い方

observation_countは、整数定数8で初期化しています。

int observation_count = 8;

8は、小数点を持たない整数定数です。観測回数は整数で表せるため、int型を使っています。

printfでは%dで表示します。

printf("観測回数:%d回\n", observation_count);

浮動小数点定数の使い方

temperatureは、浮動小数点定数21.7で初期化しています。

double temperature = 21.7;

気温は小数部分を含むため、double型を使っています。

printfでは%.1fを指定し、小数点以下を1桁表示します。

printf("現在の気温:%.1f度\n", temperature);

文字定数の使い方

statusは、文字定数'N'で初期化しています。

char status = 'N';

判定記号として1文字だけを扱うため、char型と文字定数を使用しています。

表示には%cを使います。

printf("判定記号:%c\n", status);

ここで'N'を"N"へ変更してはいけません。

char status = "N";

"N"は文字列リテラルなので、1つのchar型変数へ保存する値としては適切ではありません。コンパイラから型が合っていないことを示す警告が出る可能性があります。

正しくは、単一引用符を使います。

char status = 'N';

文字列リテラルの使い方

次のprintfでは、2つの文字列リテラルが使われています。

printf("観測メッセージ:%s\n", "現在の状態は正常です");

第1引数の次の部分は、表示形式を表す文字列リテラルです。

"観測メッセージ:%s\n"

第2引数の次の部分も文字列リテラルです。

"現在の状態は正常です"

printfは%sの位置へ第2引数の文字列を表示します。

文字列リテラルは、必ずしも変数へ保存してから使う必要はありません。この例のように、関数の引数として直接渡せます。

%cと%sを正しく使い分けよう

printfで文字を表示するときは%cを使います。

printf("%c\n", 'A');

文字列を表示するときは%sを使います。

printf("%s\n", "A");

組み合わせを整理すると、次のようになります。

表示するデータ値の例変換指定
文字'A'%c
文字列"A"%s
改行文字'\n'%c
複数の文字"ABC"%s
空文字列""%s

%cへ文字列リテラルを渡したり、%sへ文字定数を渡したりすると、変換指定と引数の型が一致しません。

正しい結果は保証されないため、必ず組み合わせを確認しましょう。

日本語はchar型1つに入るとは限らない

日本語の1文字を扱う場合は、英字の1文字と同じように考えないように注意が必要です。

UTF-8では、英字Aは通常1バイトですが、猫などの日本語は複数バイトで表現されます。

そのため、次のように通常のchar型1つへ日本語1文字を入れる方法は適切ではありません。

char animal = '猫';

処理系によっては複数文字定数として扱われたり、警告が出たりします。値も処理系依存になる可能性があります。

日本語を表示する場合は、文字列リテラルとして扱うのが基本です。

printf("%s\n", "猫");

UTF-8で保存されている場合、概念的には次のようになります。

猫を表す複数バイトのデータ + \0

日本語の見た目上の1文字と、C言語のchar型1個が必ず対応するわけではありません。

日本語の文字列にもナル文字が付く

文字列リテラル"猫"にも、末尾には\0が付きます。

ただし、UTF-8では猫という文字自体が複数バイトで表現されます。

猫のUTF-8データ
+
\0

文字列の終わりを\0で判断する考え方は、英字の文字列と同じです。

文字コードによって1文字のバイト数は変わりますが、C言語の通常の文字列がナル文字で終わる点は変わりません。

図3:1文字か文字列かを判断する流れ

この図から分かること

英字、数字、記号などの1文字を扱う場合は、文字定数として単一引用符で囲みます。

文章や複数の文字を扱う場合は、文字列リテラルとして二重引用符で囲みます。日本語は見た目が1文字でも複数バイトで表されることがあるため、通常のchar型1つとは分けて考える必要があります。

何を扱いたいかを最初に確認すれば、文字定数と文字列リテラルを選びやすくなります。

よくある間違いを確認しよう

char型へ文字列リテラルを入れる

次の書き方は正しくありません。

char grade = "A";

gradeはchar型の変数ですが、"A"は文字列リテラルです。

1文字として保存する場合は、単一引用符を使います。

char grade = 'A';

%cで文字列を表示する

次の組み合わせは正しくありません。

printf("%c\n", "A");

%cは文字を表示するための変換指定です。

文字列リテラルを表示する場合は%sを使います。

printf("%s\n", "A");

%sで文字定数を表示する

次の組み合わせも正しくありません。

printf("%s\n", 'A');

'A'は文字定数であり、文字列の先頭位置を示すものではありません。

文字定数を表示する場合は%cを使います。

printf("%c\n", 'A');

ナル文字と文字0を混同する

次の2つは別の文字です。

'0'
'\0'

'0'は画面へ表示できる数字の文字です。

'\0'は値0を持ち、文字列の終わりを表します。

文字列の終端には'\0'を使用します。

学習中に確認したい3つの基本ルール

文字定数と文字列リテラルを使うときは、次の3つを意識しましょう。

  • 単一引用符は、基本的に1文字を表す
  • 二重引用符は、文字の並びを表す
  • 文字列リテラルの最後には\0が自動的に付く

さらに、printfでは次の対応を確認します。

printf("%c\n", 'A');
printf("%s\n", "A");

コードを読むときは、引用符の種類、扱う文字数、printfの変換指定の3点を確認してみましょう。

この違いを正しく判断できるようになると、char型の変数、文字配列、ポインタ、文字列関数を学ぶときにも、データの形をイメージしやすくなります。