字符字面量

来自cppreference.com
< cpp‎ | language

语法

' 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-字符 - 下列之一
  • 来自源字符集去掉单引号(')、反斜杠(\)和换行符后的字符,
  • 转义序列,按转义序列中所定义
  • 通用字符名,按转义序列中所定义
c-字符序列 - 两个或更多个 c-字符

解释

1) 或通常字符字面量或窄字符字面量,例如 'a''\n''\13'。这种字面量具有 char 类型,且其值等于 c-字符 在执行字符集中的表示。
2) UTF-8 字符字面量,例如 u8'a'。这种字面量具有 char (C++20 前)char8_t (C++20 起) 类型,且其值等于 c-字符 的 ISO 10646 码位值,只要码位值能以单个 UTF-8 编码单元表示(即 c-字符 处于范围 0x0-0x7F(含边界)内)。
3) UTF-16 字符字面量,例如 u'字',但不是 u'🍌'u'\U0001f34c')。这种字面量具有 char16_t 类型,且其值等于 c-字符 的 ISO 10646 码位值,只要该值能以单个 UTF-16 编码单元表示(即 c-字符 处于范围 0x0-0xFFFF(含边界)内)。
4) UTF-32 字符字面量,例如 U'字'U'🍌'。这种字面量具有 char32_t 类型,且其值等于 c-字符 的 ISO 10646 码位值。
5) 宽字符字面量,例如 L'β'L'字'。这种字面量具有 wchar_t 类型,且其值等于 c-字符 在执行宽字符集中的值。
6) 通常多字符字面量,例如 'AB',为条件性支持,具有 int 类型和实现定义的值。
7) 宽多字符字面量,例如 L'AB',为条件性支持,具有 wchar_t 类型和实现定义的值。

非可编码字符

(1) 中,若 c-字符 不是数值转义序列且不可于执行字符集中表示为单个字节,则该字符字面量为条件性支持,具有 int 类型和实现定义的值。

(2-4) 中,若 c-字符 不是数值转义序列且不能于关联字符编码中表示成单个编码单元,则字符字面量非良构。

(5) 中, 若 c-字符 不是数值转义序列且不可于执行宽字符集中表示为单个编码单元(例如在 wchar_t 为 16 位的 Windows 上的非 BMP 值),则该字符字面量为条件性支持,具有 wchar_t 类型和实现定义的值。

数值转义序列

数值(八进制与十六进制)转义序列能用于指定字符的值。

若字符字面量仅含单个数值转义序列,而转义序列指定的值能以其类型的无符号版本表示,则字符字面量拥有与指定值(可能在转换到字符类型后)相同的值。

(C++23 起)

UTF-N 字符字面量任何能拥有其类型所指定的值。若其值不对应合法的 Unicode 码位,或若其对应码位不能在 UTF-N 以单个编码单元表示,则亦可以拥有该值的数值转义序列指定它。例如 u8'\xff' 良构并等于 char8_t(0xFF)

(C++23 起)

若用于通常或宽字符字面量的数值转义序列所指定的值不能分别以 charwchar_t 表示,则字符字面量的值为实现定义。

(C++23 前)

若用于有一个 c-字符 的通常或宽字符字面量的数值转义序列所指定的值能分别以 charwchar_t 的底层类型的无符号版本表示,则字面量的值是转换到字面量类型的,有该无符号整数类型与指定值的整数值。否则,程序非良构。

(C++23 起)

若用于 UTF-N 字符字面量的数值转义序列所指定的值不能以对应的 charN_t 表示,字符字面量的值为实现定义 (C++17 前)程序非良构 (C++17 起)

(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; }
 
int main()
{
    print("literal hex dump \n"
          "─────── ───────────\n");
 
    dump("a", 'a');
    dump("🍌", '🍌'); // 实现定义
    print("\n");
 
    // 通常多字符字面量
    dump("ab", 'ab'); // 实现定义
    print("\n");
 
    // UTF-16 字符字面量
    char16_t uc1 = u'a'; dump("a", uc1);
    char16_t uc2 = u'¢'; dump("¢", uc2);
    char16_t uc3 = u'猫'; dump("猫", uc3);
//  char16_t uc4 = u'🍌'; dump("🍌", uc4); // 错误: 🍌 映射到二个 UTF-16 编码单元
    print("\n");
 
    // UTF-32 字符字面量
    char32_t Uc1 = U'a'; dump("a", Uc1);
    char32_t Uc2 = U'¢'; dump("¢", Uc2);
    char32_t Uc3 = U'猫'; dump("猫", Uc3);
    char32_t Uc4 = U'🍌'; dump("🍌", Uc4);
    print("\n");
 
    // 宽字符字面量
    wchar_t wc1 = L'a'; dump("a", wc1);
    wchar_t wc2 = L'¢'; dump("¢", wc2);
    wchar_t wc3 = L'猫'; dump("猫", wc3);
    wchar_t wc4 = L'🍌'; dump("🍌", wc4);
}

可能的输出:

literal hex dump
─────── ───────────
'a'     61
'🍌'    8C 8D 9F F0
 
'ab'    62 61 00 00
 
'a'     61 00
'¢'     A2 00
'猫'    2B 73
 
'a'     61 00 00 00
'¢'     A2 00 00 00
'猫'    2B 73 00 00
'🍌'    4C F3 01 00
 
'a'     61 00 00 00
'¢'     A2 00 00 00
'猫'    2B 73 00 00
'🍌'    4C F3 01 00

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR 应用于 出版时的行为 正确行为
CWG 912 C++98 未指明非可编码的通常字符字面量 指定为条件性支持
CWG 1024 C++98 要求支持多字符字面量 设为条件性支持
CWG 1656 C++98 字符字面量中的数值转义序列的含义不明确 已指定

参阅

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