如何在utf8中获得代码点文字

How do I get a code point literal in utf8

本文关键字:代码 文字 utf8      更新时间:2023-10-16

我最近才意识到,C++17的u8字符前缀并不适用于所有utf8代码点,只适用于ASCII部分。

来自cppreference

UTF-8字符文字,例如u8'a'。这种文字的类型为char,其值等于ISO 10646的c-char代码点值,前提是代码点值可以用单个UTF-8代码单元表示。如果c-char不在Basic Latin或C0 Controls Unicode块中,则程序格式不正确。

auto hello = u8'嗨';     // ill-formed
auto world = u8"世";     // not a character
auto what = 0xE7958C;    // almost human-readable
auto wrong = u8"錯"[0];  // not even correct

如何简洁地获得utf8中的代码点文字?

编辑:对于那些想知道如何存储utf8代码点的人来说,我认为一种合理的方法就像Golang这样做。基本想法是在只需要单个代码点的情况下,将单个代码点存储在32位类型中。

编辑2:从有用的评论中提出的论点来看,没有理由让编码的utf8一直保持在32位类型中。要么对其进行解码(utf32,前缀为U),要么将其编码在前缀为u8的字符串中。

如果您想要一个代码点,那么您应该使用char32_tU作为前缀:

auto hello = U'嗨';

UTF-8将代码点存储为8位代码单元的序列。C++中的char是一个代码单元,因此它不能存储整个Unicode代码点。如果提供需要存储多个代码单元的代码点,则字符文字上的u8前缀不会编译,因为一个字符文字只能产生一个char

如果您想要一个用UTF8编码的Unicode代码点,那么您想要的是字符串文字,而不是字符文字:

auto hello = u8"嗨";

我觉得合理的一种方式就像Golang这样做。

好吧,你没有用Go,是吗?

在C++中,如果你要求一个字符文字,那么你指的是该大小类型的单个对象。u8文字将始终char。它的类型不会因字面意思而有所不同。你要求一个文字,你得到一个文字。

从你链接到的网站上可以清楚地看到,Go实际上根本没有UTF-8字符的概念。它只是具有字符文字,所有这些都是32位值。实际上,Go中的所有字符文字的行为都类似于U''

在C++中,一个字符文字恰好是一个字符对象<C++术语中的em>字符对象对应于Unicode中的代码单元。UTF-8的某些代码点需要多个代码单元。因此,并不是所有的UTF-8代码点都可以用一个字符对象来表示。可表示的代码点是Basic Latin和C0 Control块。

要表示任何UTF-8代码点,您需要一个代码单元数组,即字符串。字符串文字有一个类似的前缀:u8"☺"