字符串字面量

来自cppreference.com
< cpp‎ | language
 
 
 
表达式
概述
值类别(左值 lvalue、右值 rvalue、亡值 xvalue)
求值顺序(序列点)
常量表达式
潜在求值表达式
初等表达式
lambda 表达式(C++11)
字面量
整数字面量
浮点字面量
布尔字面量
字符字面量,包含转义序列
字符串字面量
空指针字面量(C++11)
用户定义字面量(C++11)
运算符
赋值运算符a=ba+=ba-=ba*=ba/=ba%=ba&=ba|=ba^=ba<<=ba>>=b
自增与自减++a--aa++a--
算术运算符+a-aa+ba-ba*ba/ba%b~aa&ba|ba^ba<<ba>>b
逻辑运算符a||ba&&b!a
比较运算符a==ba!=ba<ba>ba<=ba>=ba<=>b(C++20)
成员访问运算符a[b]*a&aa->ba.ba->*ba.*b
其他运算符a(...)a,ba?b:c
new 表达式
delete 表达式
throw 表达式
alignof
sizeof
sizeof...(C++11)
typeid
noexcept(C++11)
折叠表达式(C++17)
运算符的代用表示
优先级和结合性
运算符重载
默认比较(C++20)
类型转换
隐式转换
一般算术转换
const_cast
static_cast
reinterpret_cast
dynamic_cast
显式转换 (T)a, T(a)
用户定义转换
 

语法

"s字符序列 (可选)" (1)
L"s字符序列 (可选)" (2)
u8"s字符序列 (可选)" (3) (C++11 起)
u"s字符序列 (可选)" (4) (C++11 起)
U"s字符序列 (可选)" (5) (C++11 起)
前缀 (可选)R"d字符序列 (可选)(r字符序列 (可选))d字符序列 (可选)" (6) (C++11 起)

解释

s字符序列 - 一个或多个s字符
s字符 - 下列之一:
基础s字符 - 来自基础源字符集 (C++23 前)翻译字符集 (C++23 起)去掉双引号(")、反斜杠(\)和换行符后的字符
前缀 - Lu8uU 之一
d字符序列 - 一个或多个d字符,最多十六个
d字符 - 来自基础源字符集 (C++23 前)基础字符集 (C++23 起)去掉括号、反斜杠和空格后的字符
r字符序列 - 一个或多个r字符,不得包含闭序列 )d字符序列"
r字符 - 来自源字符集 (C++23 前)翻译字符集 (C++23 起)的字符
1) 通常字符串字面量。无前缀字符串字面量的类型是 const char[N],其中 N 是以执行窄编码 (C++23 前)通常字面量编码 (C++23 起)的编码单元计的字符串的大小,包含空终止符。
2) 宽字符串字面量。L"..." 字符串字面量的类型是 const wchar_t[N],其中 N 是以执行宽编码 (C++23 前)宽字面量编码 (C++23 起)的编码单元计的字符串的大小,包含空终止符。
3) UTF-8 字符串字面量。u8"..." 字符串字面量的类型是 const char[N] (C++20 前)const char8_t[N] (C++20 起),其中 N 是以 UTF-8 编码单元计的字符串的大小,包含空终止符。
4) UTF-16 字符串字面量。u"..." 字符串字面量的类型是 const char16_t[N],其中 N 是以 UTF-16 编码单元计的字符串的大小,包含空终止符。
5) UTF-32 字符串字面量。U"..." 字符串字面量的类型是 const char32_t[N],其中 N 是以 UTF-32 编码单元计的字符串的大小,包含空终止符。
6) 原始字符串字面量。用于避免转义任何字符。分隔符间的任何内容都成为字符串的一部分。如果存在前缀 ,那么具有与上述相同的含义。结尾的d字符序列 需要和开头的d字符序列 一致。

每个(来自非原始字符串字面量的)s字符 或(来自原始字符串字面量的)r字符  (C++11 起)均初始化字符串字面量对象中的对应元素。一个s字符 r字符  (C++11 起)当且仅当它被字符串字面量的关联字符编码中多于一个编码单元的序列表示时对应多于一个元素。如果字符缺少在关联字符编码中的表示,那么程序非良构。 (C++23 起)

每个数值转义序列对应单个元素。如果转义序列所指定的值适合元素类型的无符号版本,那么元素拥有(可能在转换到元素类型后的)指定值;否则(即指定值在范围外)程序非良构。 (C++23 起)

拼接

翻译阶段 6(预处理器之后),毗邻的字符串字面量会被拼接起来。即 "Hello,"  " world!" 生成(单个)字符串 "Hello, world!"。如果两个字符串的编码前缀相同(或者都没有编码前缀),那么产生的字符串将拥有相同的编码前缀(或无前缀)。

如果一个字符串有编码前缀而另一个没有,那么无编码前缀者被认为拥有与另一者相同的编码前缀。

L"Δx = %" PRId16 // 在阶段 4,PRId16 展开成 "d"
                 // 在阶段 6,L"Δx = %" 与 "d" 组成 L"Δx = %d"

如果 UTF-8 字符串字面量与宽字符串字面量毗邻,那么程序非良构。

(C++11 起)


实现可能支持或不支持任何其他编码前缀组合。这种拼接的结果由实现定义。

(C++11 起)
(C++23 前)

任何其他编码前缀组合非良构。

(C++23 起)

不求值字符串

以下语境需要字符串,但不会对它求值:

标准没有指定这些语境下是否允许使用编码前缀(除了字面量运算符名不能有编码前缀) (C++11 起)。实现的行为不一致。

(C++26 前)

这些语境下不能使用编码前缀。

不求值字符串中的每个通用字符名简单转义序列都会被它表示的翻译字符集成员替代。包含数值转义序列或条件转义序列的不求值字符串非良构。

(C++26 起)

注解

字符串字面量始终要追加空字符('\0'L'\0'char16_t() 等):因此,字符串字面量 "Hello"const char[6],并保有字符 'H''e''l''l''o''\0'

通常字符串字面量 (1) 和宽字符串字面量 (2) 的编码由实现定义。例如,gcc 用命令行选项 -fexec-charset-fwide-exec-charset 选择它们。

字符串字面量拥有静态存储期,从而在程序生存期间存在于内存中。

字符串字面量可用于初始化字符数组。如果数组初始化类似 char str[] = "foo";,那么 str 将含有字符串 "foo" 的副本。

未指定字符串字面量能否重叠以及同一字符串字面量的相继求值是否产生同一对象。这意味着以指针比较时,相同的字符串字面量比较时可能相等或不相等。

bool b = "bar" == 3 + "foobar" // 可以是 true 或 false,由实现定义

试图修改字符串字面量的行为未定义:它们可以存储于只读存储(例如 .rodata)或与其他字符串字面量合并:

const char* pc = "Hello";
char* p = const_cast<char*>(pc);
p[0] = 'M'; // 未定义行为

字符串字面量可以转换到且可以赋给非 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"; // OK :此字面量是保有 {'\xff','f','\0'} 的 const char[3]
功能特性测试 标准 注释
__cpp_char8_t 202207L (C++20)
(DR)
兼容 char8_t 并修复可移植性(允许从 UTF-8 字符串字面量初始化(unsignedchar 数组
__cpp_raw_strings 200710L (C++11) 原始字符串字面量
__cpp_unicode_literals 200710L (C++11) Unicode 字符串字面量

示例

#include <iostream>
 
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"; // OK,同
const wchar_t* s5 = L"ABCDEF";
const char32_t* s6 = U"GHI" "JKL"; // OK,同
const char32_t* s7 = U"GHIJKL";
const char16_t* s9 = "MN" u"OP" "QR"; // OK,同
const char16_t* sA = u"MNOPQR";
 
// const auto* sB = u"Mixed" U"Types";
        // C++23 前实现可能不支持;C++23 起非良构
 
const wchar_t* sC = LR"--(STUV)--"; // OK,原始字符串字面量
 
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 1759 C++11 UTF-8 字符串字面量可能会有 char 无法表示的编码单元 char 可以表示所有 UTF-8 编码单元
CWG 1823 C++98 字符串字面量是否有别是实现定义的 区别性未指明,相同字符串字面量能产生不同对象
P1854R4 C++23 包含不可编码字符的字符串字面量受条件性支持 程序非良构

参阅

用户定义字面量(C++11) 拥有用户定义后缀的字面量