命名空间
变体
操作

字符串字面量

来自 cppreference.cn
< cpp‎ | 语言
 
 
C++ 语言
通用主题
流程控制
条件执行语句
if
迭代语句 (循环)
for
范围for (C++11)
跳转语句
函数
函数声明
Lambda 函数表达式
inline 说明符
动态异常规范 (C++17 前已弃用*)
noexcept 说明符 (C++11)
异常
命名空间
类型
说明符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
存储期说明符
初始化
 
 

内容

[编辑] 语法

"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
  • 一个转义序列,如 转义序列 中所定义
  • 一个通用字符名,如 转义序列 中所定义
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 字符串字面量

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(自 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

原始字符串字面量

原始字符串字面量是以 R 为前缀的字符串字面量(语法 (2,4,6,8,10))。它们不对任何字符进行转义,这意味着分隔符 d-char-seq ()d-char-seq 之间的任何内容都成为字符串的一部分。终止 d-char-seq 是与初始 d-char-seq 相同的字符序列。

// 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 sr-char s(自 C++11 起) 序列相对应的代码单元值序列以及一个终止空字符 (U+0000) 进行初始化,顺序如下

1) 对于每个连续的 basic-s-char s、 r-char s、(自 C++11 起) 简单转义序列通用字符名,它表示的字符序列使用字符串字面量的关联字符编码编码为代码单元序列。如果字符在关联字符编码中缺少表示,则程序是非良构的。
如果关联字符编码是有状态的,则第一个此类序列以初始编码状态开始编码,并且每个后续序列以先前序列的最终编码状态开始编码。
2) 对于每个 数值转义序列,给定 v 作为由转义序列中数字序列组成的八进制或十六进制数表示的整数值,以及 T 作为字符串字面量的数组元素类型(参见上面的表格
  • 如果 v 不超过 T 的可表示值范围,则转义序列贡献一个代码单元,其值为 v
  • 否则,如果 字符串字面量的语法为 (1)(3),并且(自 C++11 起) v 不超过 T 的底层类型的对应无符号类型的可表示值范围,则转义序列贡献一个代码单元,其类型为 T 的唯一值,该值与 v mod 2S
    同余,其中 ST 的宽度。
  • 否则,程序是非良构的。
如果关联字符编码是有状态的,则所有此类序列对编码状态没有影响。
3) 每个 条件转义序列 贡献一个实现定义的代码单元序列。
如果关联字符编码是有状态的,则这些序列对编码状态的影响是实现定义的。

[编辑] 连接

相邻的字符串字面量在翻译阶段 6(预处理之后)被连接。

  • 如果两个字符串字面量属于同一种类,则连接后的字符串字面量也属于该种类。
  • 如果普通字符串字面量与宽字符串字面量相邻,则行为未定义。
(C++11 前)
  • 如果普通字符串字面量与非普通字符串字面量相邻,则连接后的字符串字面量属于后者。
  • 如果 UTF-8 字符串字面量与宽字符串字面量相邻,则程序是非良构的。
  • 任何其他组合都有条件地支持,并具有实现定义的语义。[1]
(C++23 前)
  • 任何其他组合都是非良构的。
(自 C++23 起)
(自 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"
  1. 尚无已知实现支持此类连接。

[编辑] 未求值字符串

以下上下文需要字符串字面量,但不对其求值

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


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

(C++26 前)

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

未求值字符串中的每个通用字符名和每个简单转义序列都将替换为其表示的翻译字符集成员。包含数值转义序列或条件转义序列的未求值字符串是非良构的。

(自 C++26 起)

[编辑] 注解

字符串字面量可以用于初始化字符数组。如果像 char str[] = "foo"; 这样初始化数组,则 str 将包含字符串 "foo" 的副本。

为了与 C 兼容,字符串字面量可以转换和赋值给非常量 char*wchar_t*,在 C 中,字符串字面量的类型为 char[N]wchar_t[N]。这种隐式转换已被弃用。

(C++11 前)

字符串字面量不可转换或赋值给非常量 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: 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++ 标准。

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. 如果代码单元是
    既不可在
    对应于底层类型的无符号整数类型中表示,则为非良构
    对应于底层类型
  1. 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) 带有用户定义后缀的字面量[编辑]