字串字面量
目錄 |
[編輯] 語法
" s-char-seq (可選)" |
(1) | ||||||||
R" d-char-seq (可選)( r-char-seq (可選)) d-char-seq (可選)" |
(2) | (C++11 起) | |||||||
L" s-char-seq (可選)" |
(3) | ||||||||
LR" d-char-seq (可選)( r-char-seq (可選)) d-char-seq (可選)" |
(4) | (C++11 起) | |||||||
u8" s-char-seq (可選)" |
(5) | (C++11 起) | |||||||
u8R" d-char-seq (可選)( r-char-seq (可選)) d-char-seq (可選)" |
(6) | (C++11 起) | |||||||
u" s-char-seq (可選)" |
(7) | (C++11 起) | |||||||
uR" d-char-seq (可選)( r-char-seq (可選)) d-char-seq (可選)" |
(8) | (C++11 起) | |||||||
U" s-char-seq (可選)" |
(9) | (C++11 起) | |||||||
UR" d-char-seq (可選)( r-char-seq (可選)) d-char-seq (可選)" |
(10) | (C++11 起) | |||||||
[編輯] 解釋
s-char-seq | - | 一個或多個 s-char 的序列 |
s-char | - | 以下之一 |
basic-s-char | - | 來自翻譯字元集的字元,除了雙引號 "、反斜槓 \ 或換行符 |
d-char-seq | - | 一個或多個 d-char 的序列,最長 16 個字元 |
d-char | - | 來自基本字元集的字元,除了括號、反斜槓和空格 |
r-char-seq | - | 一個或多個 r-char 的序列,但不可以包含閉合序列 ) d-char-seq" |
r-char | - | 來自翻譯字元集的字元 |
語法 | 種類 | 型別 | 編碼 | ||||
---|---|---|---|---|---|---|---|
(1,2) | 普通字串字面量 | const char[N] | 普通字面量編碼 | ||||
(3,4) | 寬字串字面量 | const wchar_t[N] | 寬字面量編碼 | ||||
(5,6) | UTF-8 字串字面量 |
|
UTF-8 | ||||
(7,8) | UTF-16 字串字面量 | const char16_t[N] | UTF-16 | ||||
(9,10) | UTF-32 字串字面量 | const char32_t[N] | UTF-32 |
在上述表格列出的型別中,N 是編碼後的碼元數量,其確定方式見下文。
普通和 UTF-8(C++11 起) 字串字面量統稱為窄字串字面量。
評估字串字面量會產生一個具有靜態儲存期的字串字面量物件。所有字串字面量是否儲存在不重疊的物件中,以及對字串字面量的連續評估是否產生相同或不同的物件,是未指定的。
嘗試修改字串字面量物件的行為是未定義的。
bool b = "bar" == 3 + "foobar"; // can be true or false, unspecified const char* pc = "Hello"; char* p = const_cast<char*>(pc); p[0] = 'M'; // undefined behavior
原始字串字面量原始字串字面量是帶有包含 // OK: contains one backslash, // equivalent to "\\" R"(\)"; // OK: contains four \n pairs, // equivalent to "\\n\\n\\n\\n" R"(\n\n\n\n)"; // OK: contains one close-parenthesis, two double-quotes and one open-parenthesis, // equivalent to ")\"\"(" R"-()""()-"; // OK: equivalent to "\n)\\\na\"\"\n" R"a( )\ a"" )a"; // OK: equivalent to "x = \"\"\\y\"\"" R"(x = ""\y"")"; // R"<<(-_-)>>"; // Error: begin and end delimiters do not match // R"-()-"-()-"; // Error: )-" appears in the middle and terminates the literal |
(C++11 起) |
[編輯] 初始化
字串字面量物件按以下順序,使用與字串字面量 s-char 序列和 r-char 序列(C++11 起) 對應的碼元值序列,加上一個終止空字元 (U+0000) 進行初始化:
T
為字串字面量的陣列元素型別(參見上方表格)- 如果 v 不超過
T
的可表示值範圍,則轉義序列貢獻一個碼元,其值為 v。 - 否則,如果字串字面量是語法 (1) 或 (3),且(C++11 起) v 不超過
T
的底層型別所對應的無符號型別的可表示值範圍,則轉義序列貢獻一個碼元,其型別為T
,唯一值為 v mod 2S
,其中 S 是T
的位寬。 - 否則,程式格式錯誤。
[編輯] 連線
相鄰的字串字面量在翻譯階段 6(預處理後)進行連線
- 如果兩個字串字面量屬於相同種類,則連線後的字串字面量也屬於該種類。
|
(C++11 前) | ||||
|
(C++11 起) |
"Hello, " "world!" // at phase 6, the 2 string literals form "Hello, world!" L"Δx = %" PRId16 // at phase 4, PRId16 expands to "d" // at phase 6, L"Δx = %" and "d" form L"Δx = %d"
- ↑ 沒有已知的實現支援這種連線。
[編輯] 未求值字串
以下上下文期望一個字串字面量,但不對其進行求值
- 語言連結規範
(C++11 起) | |
|
(C++14 起) |
|
(C++20 起) |
(C++26 起) |
在這些上下文中是否允許非普通字串字面量是未指定的,除了字面量運算子名稱必須使用普通字串字面量(C++11 起)。 |
(直到 C++26) |
在這些上下文中只允許普通字串字面量。 未求值字串中的每個通用字元名和每個簡單轉義序列都被其所表示的翻譯字元集成員替換。包含數字轉義序列或條件轉義序列的未求值字串格式錯誤。 |
(C++26 起) |
[編輯] 注意
字串字面量可用於初始化字元陣列。如果陣列像 char str[] = "foo"; 這樣初始化,str 將包含字串 "foo" 的副本。
為了與 C 相容,字串字面量可轉換為並賦值給非 const char* 或 wchar_t*,在 C 中字串字面量的型別是 char[N] 和 wchar_t[N]。此類隱式轉換已被棄用。 |
(C++11 前) |
字串字面量不可轉換為或賦值給非 const |
(C++11 起) |
字串字面量不一定是空終止字元序列:如果字串字面量包含嵌入的空字元,它表示一個包含多個字串的陣列。
const char* p = "abc\0def"; // std::strlen(p) == 3, but the array has size 8
如果在字串字面量中的十六進位制轉義序列後跟著一個有效的十六進位制數字,它將因無效轉義序列而編譯失敗。可以使用字串連線作為變通方法
//const char* p = "\xfff"; // error: hexadecimal escape sequence out of range const char* p = "\xff""f"; // OK: the literal is const char[3] holding {'\xff','f','\0'}
特性測試宏 | 值 | 標準 | 特性 |
---|---|---|---|
__cpp_char8_t |
202207L |
(C++23) (DR20) |
char8_t 相容性和可移植性修復(允許從 UTF-8 字串字面量初始化 (unsigned) char 陣列) |
__cpp_raw_strings |
200710L |
(C++11) | 原始字串字面量 |
__cpp_unicode_literals |
200710L |
(C++11) | Unicode 字串字面量 |
[編輯] 示例
#include <iostream> // array1 and array2 contains the same values: char array1[] = "Foo" "bar"; char array2[] = {'F', 'o', 'o', 'b', 'a', 'r', '\0'}; const char* s1 = R"foo( Hello World )foo"; // same as const char* s2 = "\nHello\n World\n"; // same as const char* s3 = "\n" "Hello\n" " World\n"; const wchar_t* s4 = L"ABC" L"DEF"; // OK, same as const wchar_t* s5 = L"ABCDEF"; const char32_t* s6 = U"GHI" "JKL"; // OK, same as const char32_t* s7 = U"GHIJKL"; const char16_t* s9 = "MN" u"OP" "QR"; // OK, same as const char16_t* sA = u"MNOPQR"; // const auto* sB = u"Mixed" U"Types"; // before C++23 may or may not be supported by // the implementation; ill-formed since C++23 const wchar_t* sC = LR"--(STUV)--"; // OK, raw string literal int main() { std::cout << array1 << ' ' << array2 << '\n' << s1 << s2 << s3 << std::endl; std::wcout << s4 << ' ' << s5 << ' ' << sC << std::endl; }
輸出
Foobar Foobar Hello World Hello World Hello World ABCDEF ABCDEF STUV
[編輯] 缺陷報告
下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。
缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
---|---|---|---|
CWG 411 (P2029R4) |
C++98 | 字串字面量中的轉義序列 不允許對映到多個碼元 |
允許 |
CWG 1656 (P2029R4) |
C++98 | 字串字面量中數字轉義序列所表示的 字元不明確 |
已明確 |
CWG 1759 | C++11 | UTF-8 字串字面量可能包含 無法在 char 中表示的碼元 |
char 可以表示所有 UTF-8 碼元 |
CWG 1823 | C++98 | 字串字面量是否不同 是實現定義的 |
不同性未指定,相同的 字串字面量可能產生不同的物件 |
CWG 2333 (P2029R4) |
C++11 | 不清楚是否允許在 UTF-8/16/32 字串字面量中 使用數字轉義序列 |
已明確 |
CWG 2870 | C++11 | 兩個普通字串字面量的連線結果 不明確 |
已明確 |
P1854R4 | C++98 | 包含不可編碼字元的普通和寬字串字面量 是有條件支援的 |
包含此類字面量的程式格式錯誤 |
P2029R4 | C++98 | 1. 不清楚字串字面量是否 可以包含不可編碼字元 2. 不清楚字串字面量是否可以 包含數字轉義序列,使得 它們表示的碼元無法在字面量的 陣列元素型別中表示 |
1. 對於普通和寬字串字面量 有條件支援[1] 2. 如果碼元 既不能在 底層型別對應的 無符號整型中表示,則格式錯誤 |
- ↑ P1854R4 後來作為 DR 被接受,推翻了此決議。
[編輯] 參考文獻
- C++23 標準 (ISO/IEC 14882:2024)
- 5.13.5 字串字面量 [lex.string]
- C++20 標準 (ISO/IEC 14882:2020)
- 5.13.5 字串字面量 [lex.string]
- C++17 標準 (ISO/IEC 14882:2017)
- 5.13.5 字串字面量 [lex.string]
- C++14 標準 (ISO/IEC 14882:2014)
- 2.14.5 字串字面量 [lex.string]
- C++11 標準 (ISO/IEC 14882:2011)
- 2.14.5 字串字面量 [lex.string]
- C++03 標準 (ISO/IEC 14882:2003)
- 2.13.4 字串字面量 [lex.string]
- C++98 標準 (ISO/IEC 14882:1998)
- 2.13.4 字串字面量 [lex.string]
[編輯] 另請參閱
使用者定義字面量(C++11) | 帶有使用者定義字尾的字面量 |
C 文件 關於 字串字面量
|