我只是浏览了一下寻找UTF-8代码点的一些实现(不,不是抄袭)并偶然发现this:
typedef unsigned char char8_t; typedef std::basic_string<unsigned char> u8string;
这段代码是否忽略了CHAR_BIT
只需要至少8
,但可能更大的事实?或者这在这种情况下无关紧要且代码没问题?如果是这样,那为什么呢?
另外,某人(可能是SO成员@NicolBolas?)写道:
const char *str = u8"This is a UTF-8 string.";
这几乎就是如何在C ++中将字符串文字用于UTF-8。
我认为UTF-8中的代码单元总是正好是8位! 从Unicode标准8.0.0,第2.5章:
在Unicode字符编码模型中,精确定义编码 表单指定Unicode字符的每个整数(代码点)的方式 表示为一个或多个代码单元的序列。 Unicode Standard为Unicode提供了三种不同的编码形式 字符,使用 8位,16位和32位单位。这些是 分别命名为 UTF-8 ,UTF-16和UTF-32。
(删除换行符,删除换行符上的连字符,添加强调。)
那么为什么他声称const char*
代替const uint8_t*
(或建议的假设const char8_t*
)?
答案 0 :(得分:3)
uint8_t
仅存在于内存可以作为完全 8位访问的系统上。 UTF-8没有任何此类要求。它使用适合8位的值,但不对这些值的实际存储方式施加任何要求。每个8位值可以存储为16位或32位,或者对于正在运行的系统有意义的任何值;唯一的要求是价值必须正确。
答案 1 :(得分:1)
[lex.string] / 8 普通字符串文字和UTF-8字符串文字也称为窄字符串文字。窄字符串文字的类型为“
n
const char”数组,其中n
是下面定义的字符串大小,并且具有静态存储持续时间(3.7)。
所以,无论如何,UTF-8字符串文字都是char
s的序列。
关于uint8_t
:
<强> 7.20.1.1 强>
2 typedef名称
uintN_t
指定宽度为N
且无填充位的无符号整数类型。因此,uint24_t
表示这样的无符号整数类型,其宽度恰好为24位。3这些类型是可选的。但是,如果实现提供宽度为8,16,32或64位的整数类型,没有填充位,并且(对于带有二进制补码表示的有符号类型),它应定义相应的typedef名称。
在char
大于8位的假设系统中,不会定义uint8_t
。
答案 2 :(得分:1)
那么为什么他声称
const char*
代替const uint8_t*
(或建议的假设const char8_t*
)?
因为那是标准所说的。 u8
文字字符串将解析为const char[N]
类型的数组。这就是如何定义C ++中的UTF-8文字是如何工作的。
如果系统上的char
超过8位......那就这样吧。字符串中的每个char
仍将保留0到255之间的值,这是有效UTF-8代码单元的范围。即使char
可以在此类系统上保留较大的值。
如果char
不能容纳8位......那么实现无效。根据标准的最近措辞,char
需要保留足够的位来存储每个有效的UTF-8代码单元。从技术上讲,255不是有效的UTF-8代码单元。
事实就是这样:已经有巨大的数量的代码通过char*
接受UTF-8。他们不会重写POSIX,文件系统API,以及采用不同类型的其他任何东西。
话虽如此,通过const char*
操纵一系列UTF-8代码单元是......可疑的。这是因为他们可以签名。但是,最近的标准措辞要求unsigned char
和char
之间的转换在有效的UTF-8代码单元范围内工作。也就是说,您可以将const char*
投射到const unsigned char*
,对其进行操控,然后将其转回,并确保您能够正常工作。
那个超级复杂的标准&#34;最近的标准&#34;是什么意思?
关键是允许UTF-8字符串实际工作。因为标准委员会在其无限智慧&#34;中决定不包含特殊的char8_t
UTF-8代码单元类型,所以他们必须添加措辞以使char
服务于角色。这要求转换为unsigned char
和char
的转换不能破坏UTF-8代码单元。
甚至有一个discussion topic on the C++ standard discussion forums,wording was discussed (search for 1759)。 C ++ 14的措辞说:
对于0到255(包括0和255)范围内
i
类型的每个值unsigned char
,存在j
类型的值char
,以便进行积分转换(4.7)从i
到char
为j
,从j
到unsigned char
的整数转换结果为i
。
这尤其意味着,如果签名的表示符合上述要求,则char
只能默认签名。签名char
的补码是不够的,因为负零具有特殊表示(0x80),当转换为无符号时变为常规0。
他们是否刚刚定义了一个特定的char8_t
,它必须是无符号的且至少有8位?大概。但它已经完成而且它没有改变。
答案 3 :(得分:0)
代码单元总是正好是8位。 unsigned char
被指定为至少有8位,因此UTF-8中的所有代码单元都符合unsigned char
类型。
u8"This is a UTF-8 encoded string constant"
的基本原理不是它以8位字节存储,而是以UTF-8编码,而源文件可能有不同的编码。 u8string
typedef与此一致,但如果字节超过8位,则会引起混淆。
使用unsigned char
是消除有关char
类型签名的不确定性的好方法。
答案 4 :(得分:0)
char8_t在圣地亚哥会议上被投票选为C ++ 20,因此该代码将无法编译。
但是,您将能够使用std::u8string
,但请记住,它仅适用于代码单元,不适用于代码点或字形簇,因此安全的方法是将其视为不透明的斑点并使用3rd party库进行变异它。至少现在。