字符串字面量
目录 |
[编辑] 语法
" 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 文档 关于 字符串字面量
|