本文更新至 C++20。
字符类型
-
signed char
:有符号 8 位字符类型。 -
unsigned char
:无符号 8 位字符类型。通常也用作底层内存结构的 byte 表达。 -
char
:8 位字符类型。有没有很惊讶?与int
类型族的常规不同,char
和signed char
是不同的类型。与signed char
或unsigned char
性质相同,在 x86、x64 中通常为有符号,在 arm 中通常为无符号。 -
wchar_t
:位宽足以表示其字符码点的字符类型。支持 Unicode 的平台上为 32 位,但特别地在 Windows 上为 16 位并表示一个 UTF-16 的编码。 -
char8_t
:(C++20 起)8 位字符类型。表示一个 UTF-8 的编码,与unsigned char
性质相同。 -
char16_t
:(C++11 起)至少 16 位字符类型。表示一个 UTF-16 的编码。 -
char32_t
:(C++11 起)至少 32 位字符类型。表示一个 UTF-32 的编码。
以上类型名称都是关键字,而非另外某种类型的 typedef。
字符串类型
字符串字面量可使用以下前缀:
-
L
:字符类型为wchar_t
。如L"是我"
即wchar_t[] { 0x662f, 0x6211, 0 }
。 -
u8
:(C++11 起)UTF-8 字符串,字符类型为char
,或 C++20 起char8_t
。如u8"是我"
即(char[]){ 0xe6, 0x98, 0xaf, 0xe6, 0x88, 0x91, 0 }
。 -
u
:(C++11 起)UTF-16 字符串,字符类型为char16_t
。如u"是我"
即(char16_t[]){ 0x662f, 0x6211, 0 }
。 -
U
:(C++11 起)UTF-32 字符串,字符类型为char32_t
。如U"是我"
即(char32_t[]){ 0x0000662f, 0x00006211, 0 }
。 -
R
、LR
、u8R
、uR
、UR
:(C++11 起)对应的 raw 前缀,形如R"分隔符(原始字符串)分隔符"
,取消转义,如:
R"(a
b\n)" // "a\nb\\n"
头文件
<string>
字符串类型除了 std::basic_string<char>
的别名 std::string
之外,还有:
-
std::wstring
:真身为std::basic_string<wchar_t>
。 -
std::u8string
:(C++20 起)真身为std::basic_string<char8_t>
。 -
std::u16string
:(C++11 起)真身为std::basic_string<char16_t>
。 -
std::u32string
:(C++11 起)真身为std::basic_string<char32_t>
。
编码转换
头文件
<cwchar>
std::mbstate_t
类用于表示多字节编码的状态,如余留的不完整字节。
头文件
<locale>
std::use_facet
函数用于查询一个 std::locale
而获得其 std::locale::facet
,如:
auto &cvt = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(std::locale("zh_CN.gb18030"));
std::codecvt_base::result
枚举用于表示编码转换的结果,其中:
-
ok
:成功。 -
partial
:未转换所有源字符,如目标缓冲区长度不足。 -
error
:非法字符。 -
noconv
:无转换,源与目标编码相同。
std::codecvt
类用于字符编码之间的转换,继承于 std::codecvt_base
和 std::locale::facet
。如 std::codecvt<char16_t, char8_t, std::mbstate_t>
用于在 UTF-16 和 UTF-8 之间转换。std::codecvt<char16_t, char8_t, std::mbstate_t>
、std::codecvt<char32_t, char8_t, std::mbstate_t>
和 std::codecvt<wchar_t, char, std::mbstate_t>
有特化。其中:
-
out
方法进行转换。其声明如:
std::codecvt_base::result std::codecvt<InternT, ExternT, StateT>::out(
StateT& state,
const InternT* from, const InternT* from_end, const InternT*& from_next,
ExternT* to, ExternT* to_end, ExternT*& to_next
) const;
其中,[from, from_end)
的源字符串转换到 [to, to_end)
的目标字符串,from_next
和 to_next
指向转换结束后源和目标缓冲区中的下一字节。如果源字符串结束于不完整字节,或源与目标缓冲区长度不匹配,则转换终止于让源和目标缓冲区均不越界的最后一个源字符串的完整字节。如:
#include <cwchar>
#include <locale>
int main() {
auto &cvt = std::use_facet<std::codecvt<char16_t, char8_t, std::mbstate_t>>(std::locale());
std::mbstate_t mbs;
const char8_t *si = u8"是我";
const char8_t *sin;
char16_t so[4];
char16_t *son;
auto ret = cvt.in(mbs, si, si + 4, sin, so, so + 2, son);
// ret == std::codecvt_base::result::partial, sin - si == 3, son - so == 1
}
-
in
方法与out
类似,只是参数类型上InternT
与ExternT
对调。 -
length
方法测试长度。其声明如:
int std::codecvt<InternT, ExternT, StateT>::length(
StateT& state,
const ExternT* from, const ExternT* from_end,
std::size_t max
) const;
返回 [from, from_end)
的字符串中 ExternT
类型的个数 n
,使其等效于虚拟的 .in(state, from, from_end, from_next, to, to + max, to_next)
且有 from + n == from_next
。