字符串字面量
内容 |
[编辑] 语法
" 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 的序列 |
s-char | - | 以下之一 |
basic-s-char | - | 来自 翻译字符集 的一个字符,但双引号 "、反斜杠 \ 或换行符除外 |
d-char-seq | - | 一个或多个 d-char s 的序列,长度最多 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 s 和 r-char s(从 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'}
功能测试 宏 | 值 | Std | 功能 |
---|---|---|---|
__cpp_char8_t |
202207L | (C++20) (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++ 标准。
DR | 应用于 | 已发布的行为 | 正确行为 |
---|---|---|---|
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 文档 适用于 字符串字面量
|