在 CPP 参考文档中,
我注意到
char
字符类型足够大,可以表示任何 UTF-8 八位 代码单元 (C++14 起)
和
char8_t
UTF-8字符表示的类型,要求足够大 表示任何 UTF-8 代码单元(8 位)
这是否意味着两者是同一类型?或者
char8_t
还有其他功能吗?
免责声明:我是
char8_t
P0482 和 P1423 提案的作者。
在 C++20 中,
char8_t
是与所有其他类型不同的类型。 在 C 的相关提案中,N2653、char8_t
是 unsigned char
的 typedef,类似于 char16_t
和 char32_t
的现有 typedef。
在 C++20 中,
char8_t
具有与 unsigned char
匹配的底层表示形式。 因此,它具有与 unsigned char
相同的大小(至少 8 位,但可能更大)、对齐方式和整数转换等级,但具有不同的别名规则。
特别是,
char8_t
未添加到 [basic.lval]p11 的类型列表中。 [basic.life]p6.4、[basic.types]p2 或 [basic.types]p4。 这意味着,与unsigned char
不同,它不能用于其他类型对象的底层存储,也不能用于检查其他类型对象的底层表示;换句话说,它不能用作其他类型的别名。 这样做的结果是,可以通过指向 char8_t
或 char
的指针来访问 unsigned char
类型的对象,但指向 char8_t
的指针不能用于访问 char
或 unsigned char
数据。 换句话说:
reinterpret_cast<const char *>(u8"text"); // Ok.
reinterpret_cast<const char8_t*>("text"); // Undefined behavior.
具有这些属性的独特类型的动机是:
为 UTF-8 字符数据和字符数据提供不同的类型,其编码要么依赖于区域设置,要么需要单独的规范。
启用普通字符串文字与 UTF-8 字符串文字的重载(因为它们可能具有不同的编码)。
确保 UTF-8 数据的无符号类型(
char
是有符号还是无符号由实现定义)。
通过非别名类型实现更好的性能;优化器可以更好地优化不别名其他类型的类型。
char8_t
与 char
不同。 它的行为与 unsigned char
完全相同,尽管按照 [basic.fundamental]/9
类型
表示其基础类型为char8_t
的不同类型。类型unsigned char
和char16_t
表示不同的类型,其基础类型分别为char32_t
和uint_least16_t
,在uint_least32_t
中<cstdint>.
强调我的
请注意,由于标准将其称为不同类型,因此代码如下
std::cout << std::is_same_v<unsigned char, char8_t>;
将打印
0
(false),即使 char8_t
是作为 unsigned char
实现的。 这是因为它不是别名,而是不同的类型。
另一件事需要注意的是,
char
可以实现为signed char
或unsigned char
。 这意味着 char
可能具有与 char8_t
相同的范围和表示形式,但它们仍然是不同的类型。 char
、signed char
、unsigned char
和char8_t
尺寸相同,但它们都是不同的类型。