Namespaces
Variants

String literals

From cppreference.net

ソースコードに文字列を埋め込む必要がある場合に使用される、指定された文字配列型の無名オブジェクトをその場で構築します。

目次

変更点: - 「Contents」を「目次」に翻訳 - HTMLタグ、属性、
タグ内のテキストは翻訳せず保持
- C++関連の専門用語(Syntax、Explanation、Notes、Example、References、See also)は翻訳せず保持
- 元のフォーマットと構造を完全に維持

構文

" s-char-sequence " (1)
u8" s-char-sequence " (2) (C11以降)
u" s-char-sequence " (3) (C11以降)
U" s-char-sequence " (4) (C11以降)
L" s-char-sequence " (5)

ここで

s-char-sequence - 0個以上の文字。各文字は、ソース文字セットからのマルチバイト文字(( " )、 \ 、および改行を除く)、または エスケープシーケンス で定義されている文字エスケープ、16進エスケープ、8進エスケープ 、またはユニバーサル文字名 (C99以降) のいずれか。
1) 文字列リテラル : リテラルの型は char [ N ] であり、ここで N は実行ナローエンコーディングのコード単位での文字列のサイズ(null終端文字を含む)です。配列内の各 char 要素は、実行文字セットを使用して s-char-sequence の次の文字から初期化されます。
2) UTF-8 文字列リテラル : リテラルの型は char [ N ] (C23以前) char8_t [ N ] (C23以降) であり、 N はNULL終端文字を含むUTF-8コード単位での文字列のサイズです。配列内の各 char (C23以前) char8_t (C23以降) 要素は、UTF-8エンコーディングを使用して s-char-sequence 内の次のマルチバイト文字から初期化されます。
3) 16ビットワイド文字列リテラル: リテラルの型は char16_t [ N ] であり、 N は実装定義の16ビットエンコーディング(通常はUTF-16)におけるコード単位での文字列のサイズ(ナルターミネータを含む)である。配列内の各 char16_t 要素は、実装定義のロケールで mbrtoc16 を実行するかのように初期化される。
4) 32ビットワイド文字列リテラル: リテラルの型は char32_t [ N ] であり、 N は実装定義の32ビットエンコーディング(通常はUTF-32)におけるコード単位での文字列のサイズ(ナルターミネータを含む)である。配列内の各 char32_t 要素は、実装定義のロケールで mbrtoc32 を実行するかのように初期化される。
(C23まで)
3) UTF-16文字列リテラル : リテラルの型は char16_t [ N ] であり、 N はUTF-16コード単位での文字列のサイズ(ナルターミネータを含む)である。配列内の各 char16_t 要素は、 s-char-sequence 内の次のマルチバイト文字からUTF-16エンコーディングを使用して初期化される。
4) UTF-32文字列リテラル : リテラルの型は char32_t [ N ] であり、 N はUTF-32コード単位での文字列のサイズ(ナルターミネータを含む)である。配列内の各 char32_t 要素は、 s-char-sequence 内の次のマルチバイト文字からUTF-32エンコーディングを使用して初期化される。
(C23以降)
5) ワイド文字列リテラル: リテラルの型は wchar_t [ N ] であり、 N は実行ワイドエンコーディングにおけるコード単位での文字列のサイズ(ナルターミネータを含む)です。配列内の各 wchar_t 要素は、実装定義のロケールで mbstowcs を実行するかのように初期化されます。

説明

まず、 translation phase 6 (マクロ展開後)において、隣接する文字列リテラル(つまり、空白文字のみで区切られた文字列リテラル)が連結されます。

2つのナロー文字列リテラル、または2つのワイド文字列リテラルのみが連結可能です。

(C99まで)

片方のリテラルにプレフィックスがない場合、結果の文字列リテラルはプレフィックス付きリテラルで指定された幅/エンコーディングを持ちます。

L"Δx = %" PRId16 // at phase 4, PRId16 expands to "d"
                 // at phase 6, L"Δx = %" and "d" form L"Δx = %d"
(C99以降)

2つの文字列リテラルが異なるエンコーディングプレフィックスを持つ場合、連結は実装定義である。ただし、UTF-8文字列リテラルとワイド文字列リテラルの連結はできない。

(C11以降)
(C23まで)

2つの文字列リテラルが異なるエンコーディングプレフィックスを持つ場合、連結は不適格である。

(C23以降)

第二に、 translation phase 7 において、各文字列リテラルに終端null文字が追加され、その後各リテラルは文字列リテラルの内容とnull終端文字のための1文字分を格納するのに十分な長さの静的 storage duration を持つ無名配列を初期化します。

char* p = "\x12" "3"; // 静的char[3]配列を作成し、{'\x12', '3', '\0'}を保持
                      // pを配列の最初の要素を指すように設定

文字列リテラルは 変更不可 です(実際には .rodata のような読み取り専用メモリに配置される可能性があります)。プログラムが文字列リテラルで形成された静的配列を変更しようとすると、動作は未定義となります。

char* p = "Hello";
p[1] = 'M'; // 未定義動作
char a[] = "Hello";
a[1] = 'M'; // OK: aは文字列リテラルではない

同一の文字列リテラルがメモリ内の同じ場所を参照することは、必須でも禁止されてもいません。さらに、重複する文字列リテラルや他の文字列リテラルの部分文字列である文字列リテラルは結合される可能性があります。

"def" == 3+"abcdef"; // 1または0の可能性あり、実装定義

注記

文字列リテラルは必ずしも文字列とは限りません。文字列リテラルに埋め込まれたnull文字がある場合、それは複数の文字列を含む配列を表します:

char* p = "abc\0def"; // strlen(p) == 3 ですが、配列のサイズは 8 です

文字列リテラル内で16進エスケープの後に有効な16進数字が続く場合、無効なエスケープシーケンスとしてコンパイルに失敗しますが、文字列連結を回避策として使用できます:

//char* p = "\xfff"; // エラー: 16進エスケープシーケンスが範囲外
char* p = "\xff""f"; // OK、リテラルはchar[3]で{'\xff', 'f', '\0'}を保持

文字列リテラルは 配列の初期化 に使用でき、配列のサイズが文字列リテラルのサイズより1小さい場合、ナルターミネータは無視されます:

char a1[] = "abc"; // a1はchar[4]で{'a', 'b', 'c', '\0'}を保持
char a2[4] = "abc"; // a2はchar[4]で{'a', 'b', 'c', '\0'}を保持
char a3[3] = "abc"; // a3はchar[3]で{'a', 'b', 'c'}を保持

文字列リテラル (1) およびワイド文字列リテラル (5) のエンコーディングは実装定義である。例えば、gccではこれらを コマンドラインオプション - fexec - charset および - fwide - exec - charset で選択する。

C11では混合ワイド文字列リテラルの連結が許可されていますが、ほぼすべてのコンパイラがこのような連結を拒否し(既知の唯一の例外は SDCC です)、その使用実績は不明です。この結果、C23では混合ワイド文字列リテラルの連結の許可が削除されました。

#include <inttypes.h>
#include <locale.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <uchar.h>
int main(void)
{
    char s1[] = "a猫🍌"; // or "a\u732B\U0001F34C"
#if __STDC_VERSION__ >= 202311L
    char8_t
#else
    char
#endif
    s2[] = u8"a猫🍌";
    char16_t s3[] = u"a猫🍌";
    char32_t s4[] = U"a猫🍌";
    wchar_t s5[] = L"a猫🍌";
    setlocale(LC_ALL, "en_US.utf8");
    printf("  \"%s\" is a char[%zu] holding     { ", s1, sizeof s1 / sizeof *s1);
    for(size_t n = 0; n < sizeof s1 / sizeof *s1; ++n)
        printf("0x%02X ", +(unsigned char)s1[n]);
    puts("}");
    printf(
#if __STDC_VERSION__ >= 202311L
    "u8\"%s\" is a char8_t[%zu] holding  { "
#else
    "u8\"%s\" is a char[%zu] holding     { "
#endif
, s2, sizeof s2 / sizeof *s2);
    for(size_t n = 0; n < sizeof s2 / sizeof *s2; ++n)
#if __STDC_VERSION__ >= 202311L
       printf("0x%02X ", s2[n]);
#else
       printf("0x%02X ", +(unsigned char)s2[n]);
#endif
    puts("}");
    printf(" u\"a猫🍌\" is a char16_t[%zu] holding { ", sizeof s3 / sizeof *s3);
    for(size_t n = 0; n < sizeof s3 / sizeof *s3; ++n)
       printf("0x%04" PRIXLEAST16" ", s3[n]);
    puts("}");
    printf(" U\"a猫🍌\" is a char32_t[%zu] holding { ", sizeof s4 / sizeof *s4);
    for(size_t n = 0; n < sizeof s4 / sizeof *s4; ++n)
       printf("0x%08" PRIXLEAST32" ", s4[n]);
    puts("}");
    printf(" L\"%ls\" is a wchar_t[%zu] holding  { ", s5, sizeof s5 / sizeof *s5);
    for(size_t n = 0; n < sizeof s5 / sizeof *s5; ++n)
       printf("0x%08X ", (unsigned)s5[n]);
    puts("}");
}

出力例:

  "a猫🍌" is a char[9] holding     { 0x61 0xE7 0x8C 0xAB 0xF0 0x9F 0x8D 0x8C 0x00 }
u8"a猫🍌" is a char[9] holding     { 0x61 0xE7 0x8C 0xAB 0xF0 0x9F 0x8D 0x8C 0x00 }
 u"a猫🍌" is a char16_t[5] holding { 0x0061 0x732B 0xD83C 0xDF4C 0x0000 }
 U"a猫🍌" is a char32_t[4] holding { 0x00000061 0x0000732B 0x0001F34C 0x00000000 }
 L"a猫🍌" is a wchar_t[4] holding  { 0x00000061 0x0000732B 0x0001F34C 0x00000000 }

参考文献

  • C23規格 (ISO/IEC 9899:2024):
  • 6.4.5 文字列リテラル (p: TBD)
  • C17規格 (ISO/IEC 9899:2018):
  • 6.4.5 文字列リテラル (p: 50-52)
  • C11規格 (ISO/IEC 9899:2011):
  • 6.4.5 文字列リテラル (p: 70-72)
  • C99規格 (ISO/IEC 9899:1999):
  • 6.4.5 文字列リテラル (p: 62-63)
  • C89/C90標準 (ISO/IEC 9899:1990):
  • 3.1.4 文字列リテラル

関連項目

C++ ドキュメント for string literal
翻訳内容: - "C++ documentation" → "C++ ドキュメント" - "for" → "for"(接続詞としての役割を考慮し、日本語の文脈で自然なためそのまま保持) - "string literal" → 翻訳せずに保持(C++専門用語のため) HTMLタグ、属性、およびC++専門用語はすべて原文のまま保持されています。