字符字面量
语法
'c字符 '
|
(1) | ||||||||
u8'c字符 '
|
(2) | (C++17 起) | |||||||
u'c字符 '
|
(3) | (C++11 起) | |||||||
U'c字符 '
|
(4) | (C++11 起) | |||||||
L'c字符 '
|
(5) | ||||||||
'c字符序列 '
|
(6) | ||||||||
L'c字符序列 '
|
(7) | (C++23 前) | |||||||
| c字符 | - | 下列之一: |
| 基本c字符 | - | 来自基本源字符集(C++23 前)翻译字符集(C++23 起)去掉单引号(')、反斜杠(\)和换行符后的字符
|
| c字符序列 | - | 两个或更多个c字符 |
解释
'a' 或 '\n' 或 '\13'。这种字面量具有 char 类型,且它的值等于c字符 在执行字符集中的表示(C++23 前)来自普通字面量编码的对应代码单元(C++23 起)。u8'a'。这种字面量具有 char(C++20 前)char8_t(C++20 起) 类型,且它的值等于c字符 的 ISO/IEC 10646 码位值,只要码位值能以单个 UTF-8 代码单元表示(即c字符 处于范围 0x0-0x7F(含边界)内)。u'猫',但不是 u'🍌'(u'\U0001f34c')。这种字面量具有 char16_t 类型,且它的值等于c字符 的 ISO/IEC 10646 码位值,只要该值能以单个 UTF-16 代码单元表示(即c字符 处于范围 0x0-0xFFFF(含边界)内)。L'β' 或 L'猫'。这种字面量具有 wchar_t 类型,且它的值等于c字符 在执行宽字符集中的表示(C++23 前)来自宽字面量编码的对应代码单元(C++23 起)。'AB',具有 int 类型和实现定义的值。L'AB',具有 wchar_t 类型和实现定义的值。不可编码字符
wchar_t 是 16 位的 Windows 上的非 BMP 值),那么程序非良构。| (C++23 前) |
数值转义序列
数值(八进制与十六进制)转义序列能用于指定字符的值。
|
如果字符字面量只包含一个数值转义序列,且该转义序列指定的值能以它的类型的无符号版本表示,那么字符字面量拥有与指定值(可能在转换到字符类型后)相同的值。 UTF-N 字符字面量能拥有它的类型可表示的任意值。即使该值对应的码位在 Unicode 中不合法或在 UTF-N 中无法以单个代码单元表示,该值的数值转义序列依然可以指定它。例如 |
(C++23 起) |
|
如果一个普通或宽字符字面量中用来指定值的数值转义序列指定了一个无法分别以 |
(C++23 前) |
|
如果一个有单个c字符 的普通或宽字符字面量中用来指定值的数值转义序列所指定的值能分别以 |
(C++23 起) |
|
如果一个 UTF-N 字符字面量中用来指定值的数值转义序列所指定的值不能以对应的 |
(C++11 起) |
注解
多字符字面量是 C 从 B 编程语言继承而来的。尽管 C 或 C++ 标准不指定,大多数编译器(值得注意的例外是 MSVC )也如 B 中所指定实现多字符字面量:字面量中的每个字符的值以大端序零填充右对齐顺序初始化结果整数的相继字节,例如 '\1' 的值为 0x00000001 而 '\1\2\3\4' 的值为 0x01020304 。
在 C 中,诸如 'a' 或 '\n' 之类的字符常量具有 int 类型,而不是 char。
示例
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string_view>
template<typename CharT>
void dump(std::string_view s, const CharT c)
{
const uint8_t* data{reinterpret_cast<const uint8_t*>(&c)};
std::cout << s << " \t" << std::hex
<< std::uppercase << std::setfill('0');
for (auto i{0U}; i != sizeof(CharT); ++i)
std::cout << std::setw(2) << static_cast<unsigned>(data[i]) << ' ';
std::cout << '\n';
}
void print(std::string_view str = "") { std::cout << str << '\n'; }
int main()
{
print("普通字符字面量:");
char c1 = 'a'; dump("'a'", c1);
char c2 = '\x2a'; dump("'*'", c2);
print("\n" "普通多字符字面量:");
int mc1 = 'ab'; dump("'ab'", mc1); // 由实现定义
int mc2 = 'abc'; dump("'abc'", mc2); // 由实现定义
print("\n" "UTF-8 字符字面量:");
char8_t C1 = u8'a'; dump("u8'a'", C1);
// char8_t C2 = u8'¢'; dump("u8'¢'", C2); // 错误:¢ 会映射到两个 UTF-8 代码单元
// char8_t C3 = u8'猫'; dump("u8'猫'", C3); // 错误:猫 会映射到三个 UTF-8 代码单元
// char8_t C4 = u8'🍌'; dump("u8'🍌'", C4); // 错误:🍌 会映射到四个 UTF-8 代码单元
print("\n" "UTF-16 字符字面量:");
char16_t uc1 = u'a'; dump("u'a'", uc1);
char16_t uc2 = u'¢'; dump("u'¢'", uc2);
char16_t uc3 = u'猫'; dump("u'猫'", uc3);
// char16_t uc4 = u'🍌'; dump("u'🍌'", uc4); // 错误:🍌 会映射到两个 UTF-16 代码单元
print("\n" "UTF-32 字符字面量:");
char32_t Uc1 = U'a'; dump("U'a'", Uc1);
char32_t Uc2 = U'¢'; dump("U'¢'", Uc2);
char32_t Uc3 = U'猫'; dump("U'猫'", Uc3);
char32_t Uc4 = U'🍌'; dump("U'🍌'", Uc4);
print("\n" "宽字符字面量:");
wchar_t wc1 = L'a'; dump("L'a'", wc1);
wchar_t wc2 = L'¢'; dump("L'¢'", wc2);
wchar_t wc3 = L'猫'; dump("L'猫'", wc3);
wchar_t wc4 = L'🍌'; dump("L'🍌'", wc4); // 从 C++23 开始在 Windows 上不支持
}
可能的输出:
普通字符字面量:
'a' 61
'*' 2A
普通多字符字面量:
'ab' 62 61 00 00
'abc' 63 62 61 00
UTF-8 字符字面量:
u8'a' 61
UTF-16 字符字面量:
u'a' 61 00
u'¢' A2 00
u'猫' 2B 73
UTF-32 字符字面量:
U'a' 61 00 00 00
U'¢' A2 00 00 00
U'猫' 2B 73 00 00
U'🍌' 4C F3 01 00
宽字符字面量:
L'a' 61 00 00 00
L'¢' A2 00 00 00
L'猫' 2B 73 00 00
L'🍌' 4C F3 01 00
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
| 缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
|---|---|---|---|
| CWG 912 | C++98 | 未指明不可编码的通常字符字面量 | 指定为条件性支持 |
| CWG 1024 | C++98 | 要求支持多字符字面量 | 改为条件性支持 |
| CWG 1656 | C++98 | 字符字面量中的数值转义序列的含义不明确 | 已指定 |
| P1854R4 | C++98 | 包含不可编码字符的字符字面量受条件性支持 | 程序非良构 |
引用
- C++23 标准(ISO/IEC 14882:2024):
- 5.13.3 Character literals [lex.ccon]
- C++20 标准(ISO/IEC 14882:2020):
- 5.13.3 Character literals [lex.ccon]
- C++17 标准(ISO/IEC 14882:2017):
- 5.13.3 Character literals [lex.ccon]
- C++14 标准(ISO/IEC 14882:2014):
- 2.14.3 Character literals [lex.ccon]
- C++11 标准(ISO/IEC 14882:2011):
- 2.14.3 Character literals [lex.ccon]
- C++03 标准(ISO/IEC 14882:2003):
- 2.13.2 Character literals [lex.ccon]
- C++98 标准(ISO/IEC 14882:1998):
- 2.13.2 Character literals [lex.ccon]
参阅
| 用户定义字面量 (C++11) | 拥有用户定义后缀的字面量 |
字符常量的 C 文档
| |