字符串字面量
语法
1 | " | s-char-sequence | (可选) | " | ||||||||||
2 | L | " | s-char-sequence | (可选) | " | |||||||||
3 | u8 | " | s-char-sequence | (可选) | " | |||||||||
4 | u | " | s-char-sequence | (可选) | " | |||||||||
5 | U | " | s-char-sequence | (可选) | " | |||||||||
6 | prefix(optional) | R | " | d-char-sequence | (可选) | ( | r-char-sequence | (可选) | ) | d-char-sequence | (可选) | " |
解释
pub | s-char-sequence | 一个或多个s-char的序列 |
pub | s-char | 之一 |
pub | basic-s-char | 来自翻译字符集的字符,但不包括双引号" 、反斜杠\ 或换行符 |
pub | prefix | L, u8, u, U 中的一个 |
pub | d-char-sequence | 一个或多个d-char的序列,最多16个字符 |
pub | d-char | 来自基本字符集的字符,但不包括括号、反斜杠和空格 |
pub | r-char-sequence | 一个或多个r-char的序列,但不得包含结尾序列)d-char-sequence" |
pub | r-char | 来自翻译字符集的字符 |
- 普通字符串字面量。未加前缀的字符串字面量的类型为const char[N],其中
N
是普通字面量编码的代码单元数,包括空终止符。 - 宽字符串字面量。
L"..."
字符串字面量的类型为const wchar_t[N],其中N
是宽字面量编码的代码单元数,包括空终止符。 - UTF-8字符串字面量。
u8"..."
字符串字面量的类型为const char[N] (until C++20) const char8_t[N] (since C++20),其中N
是UTF-8代码单元数,包括空终止符。 - UTF-16字符串字面量。
u"..."
字符串字面量的类型为const char16_t[N],其中N
是UTF-16代码单元数,包括空终止符。 - UTF-32字符串字面量。
U"..."
字符串字面量的类型为const char32_t[N],其中N
是UTF-32代码单元数,包括空终止符。 - 原始字符串字面量。用于避免转义任何字符。分隔符之间的任何内容都成为字符串的一部分。如果存在prefix,其含义与上面描述的相同。终止的d-char-sequence与初始的d-char-sequence相同。
每个s-char(最初来自非原始字符串字面量)或r-char(最初来自原始字符串字面量) (since C++11)初始化字符串字面量对象中的相应元素。当且仅当s-char或r-char (since C++11)由字符串字面量相关字符编码中的多个代码单元序列表示时,它才对应一个以上的元素。如果字符在相关字符编码中没有表示,程序格式错误。 (since C++23)
每个数字转义序列对应一个元素。如果转义序列指定的值适合元素类型的无符号版本,则元素具有指定的值(可能在转换为元素类型后);否则(指定的值超出范围),程序格式错误。 (since C++23)
Concatenation
并排放置的字符串字面量在翻译阶段6(预处理器之后)进行连接。也就是说,"Hello," " world!"
生成(单个)字符串"Hello, world!"
。如果两个字符串具有相同的编码前缀(或都没有),则生成的字符串将具有相同的编码前缀(或没有前缀)。
如果一个字符串有编码前缀而另一个没有,则没有前缀的字符串将被视为具有与另一个相同的编码前缀。
L"Δx = %" PRId16 // at phase 4, PRId16 expands to "d"
// at phase 6, L"Δx = %" and "d" form L"Δx = %d"
如果UTF-8字符串字面量和宽字符串字面量并排放置,则程序格式错误。
(自 C++11 起)任何其他编码前缀组合都支持条件性,具有实现定义的语义。(没有已知的实现支持此类连接。)
(until C++23) (since C++11)任何其他编码前缀组合都是格式错误的。
(自 C++23 起)Unevaluated strings
以下上下文需要字符串字面量,但不会对其进行评估
- 语言链接规范
- static_assert (since C++11)
- 字面量运算符名称 (since C++11)
- [[deprecated]] (since C++14)
- [[nodiscard]] (since C++20)
在这些上下文中不允许使用编码前缀。
每个通用字符名和每个简单转义序列在未评估的字符串中被替换为其表示的翻译字符集成员。包含数字转义序列或条件转义序列的未评估字符串是格式错误的。
(自 C++26 起)备注
空字符('\0'
、L'\0'
、char16_t()
等)始终附加到字符串字面量:因此,字符串字面量"Hello"
是一个const char[6]
,包含字符
普通字符串字面量(1)和宽字符串字面量(2)的编码是实现定义的。例如,gcc通过命令行选项-fexec-charset
和-fwide-exec-charset
选择它们。
字符串字面量具有静态存储持续时间,因此在程序生命周期内存在于内存中。
字符串字面量可用于初始化字符数组。如果一个数组的初始化方式是char str[] = "foo";
,那么str
将包含字符串的副本
字符串字面量是否重叠以及连续评估字符串字面量是否产生相同对象是未指定的。这意味着相同的字符串字面量在通过指针比较时可能相等,也可能不相等。
bool b = "bar" == 3 + "foobar"; // could be true or false, implementation-defined
尝试修改字符串字面量会导致未定义行为:它们可能存储在只读存储区(如.rodata)或与其他字符串字面量组合
const char* pc = "Hello";
char* p = const_cast<char*>(pc);
p[0] = 'M'; // undefined behavior
字符串字面量不可转换为或赋值给非const CharT*。如果需要进行此类转换,必须使用显式转换(例如 const_cast)。 (自 C++11 起)
字符串字面量不一定是空终止字符序列:如果字符串字面量包含嵌入的空字符,则它表示一个包含多个字符串的数组。
const char* p = "abc\0def"; // std::strlen(p) == 3, but the array has size 8
如果在字符串字面量中的十六进制转义符后跟一个有效的十六进制数字,则会因无效的转义序列而编译失败。字符串连接可以用作一种解决方法
//const char* p = "\xfff"; // error: hex escape sequence out of range
const char* p = "\xff""f"; // OK: the literal is const char[3] holding {'\xff','f','\0'}
特性测试宏 | Value | 标准 | 注释 |
---|---|---|---|
__cpp_char8_t | 202207L | (C++20) (DR) | char8_t 兼容性和可移植性修复(允许将(unsigned) char 数组初始化为UTF-8字符串字面量) |
__cpp_raw_strings | 200710L | (C++11) | 原始字符串字面量 |
__cpp_unicode_literals | 200710L | (C++11) | Unicode 字符串字面量 |
示例
#include <iostream>
char array1[] = "Foo" "bar";
// same as
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 1759 | (C++11) | UTF-8字符串字面量可能包含char中无法表示的代码单元 | char可以表示所有UTF-8代码单元 |
CWG 1823 | (C++98) | 字符串字面量是否不同是实现定义的 | 不同性是未指定的,相同的字符串字面量可以产生不同的对象 |
P1854R4 | (C++23) | 包含不可编码字符的字符串字面量曾被条件性支持 | 程序格式错误 |
参考文献
- C++23 标准 (ISO/IEC 14882:2023)
- 5.13.5 String literals [lex.string]
- C++20 标准 (ISO/IEC 14882:2020)
- 5.13.5 String literals [lex.string]
- C++17 标准 (ISO/IEC 14882:2017)
- 5.13.5 String literals [lex.string]
- C++14 标准 (ISO/IEC 14882:2014)
- 2.14.5 String literals [lex.string]
- C++11 标准 (ISO/IEC 14882:2011)
- 2.14.5 String literals [lex.string]
- C++03 标准 (ISO/IEC 14882:2003)
- 2.13.4 String literals [lex.string]
- C++98 标准 (ISO/IEC 14882:1998)
- 2.13.4 String literals [lex.string]