Namespaces
Variants

String literal

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

目录

语法

" 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 - 来自 基本源字符集 (C++23前) 翻译字符集 (C++23起) 的字符,但不包括双引号 " 、反斜杠 \ 或换行符
d-char-seq - 一个或多个 d-char 的序列,长度最多16个字符
d-char - 来自 基本源字符集 (C++23前) 基本字符集 (C++23起) 的字符,但不包括圆括号、反斜杠和 空白字符
r-char-seq - 一个或多个 r-char 的序列,但不能包含结束序列 ) d-char-seq "
r-char - 来自 基本源字符集 (C++23前) 翻译字符集 (C++23起) 的字符

语法 种类 类型 编码
(1,2) 普通字符串字面量 const char [ N ] 普通字面量编码
(3,4) 宽字符串字面量 const wchar_t [ N ] 宽字面量编码
(5,6) UTF-8 字符串字面量

const char [ N ]

(C++20 前)

const char8_t [ N ]

(C++20 起)
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 (since C++11) 字符串字面量统称为窄字符串字面量。

对字符串字面量的求值会产生一个具有静态 存储期 的字符串字面量对象。是否所有字符串字面量都存储在 互不重叠的对象 中,以及连续对同一字符串字面量的求值会得到相同对象还是不同对象,均未作规定。

尝试修改字符串字面量对象的效果是未定义的。

bool b = "bar" == 3 + "foobar"; // 结果可能为 true 或 false,未定义行为
const char* pc = "Hello";
char* p = const_cast<char*>(pc);
p[0] = 'M'; // 未定义行为

原始字符串字面量

原始字符串字面量是以包含 R 的前缀开头的字符串字面量(语法 (2,4,6,8,10) )。它们不会转义任何字符,这意味着在定界符 d-char-seq  ( ) d-char-seq 之间的所有内容都会成为字符串的一部分。结束的 d-char-seq 必须与起始的 d-char-seq 是完全相同的字符序列。

// OK: 包含一个反斜杠,
// 等价于 "\\"
R"(\)";
// OK: 包含四个 \n 对,
// 等价于 "\\n\\n\\n\\n"
R"(\n\n\n\n)";
// OK: 包含一个右括号、两个双引号和一个左括号,
// 等价于 ")\"\"("
R"-()""()-";
// OK: 等价于 "\n)\\\na\"\"\n"
R"a(
)\
a""
)a";
// OK: 等价于 "x = \"\"\\y\"\""
R"(x = ""\y"")";
// R"<<(-_-)>>"; // 错误:起始和结束定界符不匹配
// R"-()-"-()-"; // 错误:)-" 出现在中间并终止了字面量
(since C++11)

初始化

字符串字面量对象按照以下顺序,使用对应字符串字面量中 s-char 序列 r-char 序列 (C++11 起) 的代码单元值序列进行初始化,并附加终止空字符 (U+0000):

1) 对于每个连续的 basic-s-char 序列 r-char 序列 (C++11 起) 简单转义序列 通用字符名 ,其所表示的字符序列将使用字符串字面量的关联字符编码被编码为代码单元序列。若某个字符在关联字符编码中缺乏表示形式,则程序非良构。
若关联字符编码具有状态性,首个此类序列从初始编码状态开始编码,每个后续序列则从前一序列的最终编码状态开始编码。
2) 对于每个 数值转义序列 ,设 v 为由转义序列中数字组成的八进制或十六进制数所表示的整数值, T 为字符串字面量的数组元素类型(参见 上表 ):
  • v 未超过 T 的可表示值范围,则转义序列贡献一个值为 v 的单个代码单元。
  • 否则,若 字符串字面量采用语法 (1) (3) ,且 (C++11 起) v 未超过 T 底层类型对应无符号类型的可表示值范围,则转义序列贡献一个 T 类型的唯一值代码单元,该值同余于 v mod 2 S
    ,其中 S T 的位宽。
  • 否则,程序非良构。
如果关联的字符编码具有状态性,所有此类序列对编码状态均不产生影响。
3) 每个 条件转义序列 会产生一个由实现定义的代码单元序列。
若关联字符编码具有状态依赖性,则这些序列对编码状态的影响由实现定义。

连接

相邻的字符串字面量会在 翻译阶段6 (预处理之后)进行连接:

  • 如果两个字符串字面量属于同一 类别 ,则拼接后的字符串字面量也属于该类别。
  • 若普通字符串字面量与宽字符串字面量相邻,则行为未定义。
(C++11 前)
  • 若普通字符串字面量与非普通字符串字面量相邻,则拼接后的字符串字面量类型与后者相同。
  • 若 UTF-8 字符串字面量与宽字符串字面量相邻,则程序非良构。
  • 其他任意组合在实现定义语义下有条件支持。 [1]
(C++23 前)
  • 其他任意组合均为非良构。
(C++23 起)
(C++11 起)
"Hello, " "world!" // 在第6阶段,两个字符串字面量组成 "Hello, world!"
L"Δx = %" PRId16   // 在第4阶段,PRId16 扩展为 "d"
                   // 在第6阶段,L"Δx = %" 和 "d" 组成 L"Δx = %d"
  1. 目前没有已知的实现支持此类连接。

未求值字符串

以下上下文期望字符串字面量,但不进行求值:

(自 C++11 起)
(自 C++14 起)
(自 C++20 起)
(自 C++26 起)


未指明是否允许在这些上下文中使用非普通字符串字面量 ,但字面量运算符名必须使用普通字符串字面量 (C++11 起)

(C++26 前)

这些上下文中仅允许使用普通字符串字面量。

未求值字符串中的每个 通用字符名 和每个 简单转义序列 均被其表示的 翻译字符集 成员替换。包含数值转义序列或条件转义序列的未求值字符串是病式的。

(C++26 起)

注释

字符串字面量可用于 初始化字符数组 。若数组以 char str [ ] = "foo" ; 形式初始化,则 str 将包含字符串 "foo" 的副本。

字符串字面量可转换并赋值给非const char * wchar_t * ,这是为了兼容C语言(在C语言中字符串字面量类型为 char [ N ] wchar_t [ N ] )。这种隐式转换已被弃用。

(C++11前)

字符串字面量不可转换或赋值给非const CharT* 。如需进行此类转换,必须使用显式转换(例如 const_cast )。

(C++11起)

字符串字面量不一定是空终止字符序列:如果字符串字面量包含嵌入的空字符,它表示包含多个字符串的数组。

const char* p = "abc\0def"; // std::strlen(p) == 3,但该数组的大小为8

如果在字符串字面值中,十六进制转义序列后紧跟一个有效的十六进制数字,会导致编译失败,因为会被视为无效的转义序列。可以使用字符串连接作为解决方案:

//const char* p = "\xfff"; // 错误:十六进制转义序列超出范围
const char* p = "\xff""f"; // 正确:该字面量为 const char[3] 类型,包含 {'\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 和 array2 包含相同的值:
char array1[] = "Foo" "bar";
char array2[] = {'F', 'o', 'o', 'b', 'a', 'r', '\0'};
const char* s1 = R"foo(
Hello
  World
)foo";
// 等同于
const char* s2 = "\nHello\n  World\n";
// 等同于
const char* s3 = "\n"
                 "Hello\n"
                 "  World\n";
const wchar_t* s4 = L"ABC" L"DEF"; // 正确,等同于
const wchar_t* s5 = L"ABCDEF";
const char32_t* s6 = U"GHI" "JKL"; // 正确,等同于
const char32_t* s7 = U"GHIJKL";
const char16_t* s9 = "MN" u"OP" "QR"; // 正确,等同于
const char16_t* sA = u"MNOPQR";
// const auto* sB = u"Mixed" U"Types";
        // C++23 之前可能由实现支持也可能不支持;
        // 自 C++23 起格式错误
const wchar_t* sC = LR"--(STUV)--"; // 正确,原始字符串字面量
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. 若代码单元既无法在底层类型
对应的无符号整数类型中表示,
则非良构
  1. P1854R4 后来被接受为缺陷报告,推翻了此项决议。

参考文献

  • 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 文档 关于 字符串字面量