C++20 'char8_t' 与我们旧的 'char' 相同吗?

问题描述 投票:0回答:2

在 CPP 参考文档中,

我注意到

char

字符类型足够大,可以表示任何 UTF-8 八位 代码单元 (C++14 起)

char8_t

UTF-8字符表示的类型,要求足够大 表示任何 UTF-8 代码单元(8 位)

这是否意味着两者是同一类型?或者

char8_t
还有其他功能吗?

c++ c++14 language-lawyer c++20
2个回答
113
投票

免责声明:我是

char8_t
P0482P1423 提案的作者。

在 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.

具有这些属性的独特类型的动机是:

  1. 为 UTF-8 字符数据和字符数据提供不同的类型,其编码要么依赖于区域设置,要么需要单独的规范。

  2. 启用普通字符串文字与 UTF-8 字符串文字的重载(因为它们可能具有不同的编码)。

  3. 确保 UTF-8 数据的无符号类型(

    char
    是有符号还是无符号由实现定义)。

  4. 通过非别名类型实现更好的性能;优化器可以更好地优化不别名其他类型的类型。


59
投票

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
尺寸相同,但它们都是不同的类型。

© www.soinside.com 2019 - 2024. All rights reserved.