文字列リテラル
ソースコード内に埋め込む必要のある文字列を表現するために使用される、指定された文字配列型の名前のないオブジェクトをインプレースで構築します。
目次 |
[編集] 構文
" 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 | - | ゼロ個以上の文字。各文字は、ソース文字セットからのマルチバイト文字("、\、改行を除く)、または エスケープシーケンスで定義されている文字エスケープ、16進エスケープ、8進エスケープ、またはユニバーサル文字名(C99以降)のいずれかです。 |
N は、ヌル終端文字を含む、実行時ナローエンコーディングのコードユニットでの文字列のサイズです。配列内の各 char 要素は、実行時文字セットを使用して、s-char-sequence の次の文字から初期化されます。N は、ヌル終端文字を含む、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 要素は、UTF-16エンコーディングを使用して、s-char-sequence の次のマルチバイト文字から初期化されます。4) UTF-32 文字列リテラル: リテラルの型は char32_t[N] です。ここで、 N は、ヌル終端文字を含む、UTF-32コードユニットでの文字列のサイズです。配列内の各 char32_t 要素は、UTF-32エンコーディングを使用して、s-char-sequence の次のマルチバイト文字から初期化されます。 |
(C23以降) |
N は、ヌル終端文字を含む、実行時ワイドエンコーディングのコードユニットでの文字列のサイズです。配列内の各 wchar_t 要素は、実装定義のロケールで mbstowcs を実行した場合と同様に初期化されます。[編集] 説明
まず、翻訳フェーズ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つの文字列リテラルが異なるエンコーディングプレフィックスを持つ場合、連結はill-formed(不正な形式)です。 |
(C23以降) |
次に、翻訳フェーズ7で、各文字列リテラルに終端ヌル文字が追加され、その後、各リテラルは、文字列リテラルの内容とヌル終端文字用の1文字を格納するのに十分な長さを持つ、静的記憶域期間を持つ名前のない配列を初期化します。
char* p = "\x12" "3"; // creates a static char[3] array holding {'\x12', '3', '\0'} // sets p to point to the first element of the array
文字列リテラルは変更できません(実際、.rodata のような読み取り専用メモリに配置される可能性があります)。プログラムが文字列リテラルによって形成された静的配列を変更しようとすると、未定義の動作となります。
char* p = "Hello"; p[1] = 'M'; // Undefined behavior char a[] = "Hello"; a[1] = 'M'; // OK: a is not a string literal
同一の文字列リテラルがメモリ内の同じ場所を参照することは、必要でも禁止されてもいません。さらに、重複する文字列リテラル、または他の文字列リテラルの部分文字列である文字列リテラルは結合される可能性があります。
"def" == 3+"abcdef"; // may be 1 or 0, implementation-defined
[編集] 注記
文字列リテラルは必ずしも文字列ではありません。文字列リテラルに埋め込まれたヌル文字がある場合、それは複数の文字列を含む配列を表します。
char* p = "abc\0def"; // strlen(p) == 3, but the array has size 8
有効な16進数が16進エスケープの後に文字列リテラルで続いている場合、無効なエスケープシーケンスとしてコンパイルに失敗しますが、文字列連結を回避策として使用できます。
//char* p = "\xfff"; // error: hex escape sequence out of range char* p = "\xff""f"; // okay, the literal is char[3] holding {'\xff', 'f', '\0'}
文字列リテラルは配列の初期化に使用できます。配列のサイズが文字列リテラルのサイズより1小さい場合、ヌル終端文字は無視されます。
char a1[] = "abc"; // a1 is char[4] holding {'a', 'b', 'c', '\0'} char a2[4] = "abc"; // a2 is char[4] holding {'a', 'b', 'c', '\0'} char a3[3] = "abc"; // a3 is char[3] holding {'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++ のドキュメント (文字列リテラル について)
|